diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/Print.Application/ForumApplicationAutoMapperProfile.cs b/Print.Application/ForumApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..447bfd8 --- /dev/null +++ b/Print.Application/ForumApplicationAutoMapperProfile.cs @@ -0,0 +1,17 @@ +using AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Print.Application +{ + public class ForumApplicationAutoMapperProfile : Profile + { + public ForumApplicationAutoMapperProfile() + { + + } + } +} diff --git a/Print.Application/ForumApplicationModule.cs b/Print.Application/ForumApplicationModule.cs new file mode 100644 index 0000000..3be45da --- /dev/null +++ b/Print.Application/ForumApplicationModule.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.DependencyInjection; +using Print.Forum.Application.Contracts; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace Print.Application; + + + + + +/// +/// 项目模块依赖、组件依赖 +/// +[DependsOn( + typeof(AbpAutoMapperModule), + typeof(ForumApplicationContractsModule) + )] +public class ForumApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var services = context.Services; + // 添加ObjectMapper注入 + services.AddAutoMapperObjectMapper(); + + // Abp AutoMapper设置 + Configure(config => + { + // 添加对应依赖关系Profile + config.AddMaps(); + }); + } +} \ No newline at end of file diff --git a/Print.Application/Print.Application.csproj b/Print.Application/Print.Application.csproj new file mode 100644 index 0000000..470b4cc --- /dev/null +++ b/Print.Application/Print.Application.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Print.Application/Print/EzioInterop.cs b/Print.Application/Print/EzioInterop.cs new file mode 100644 index 0000000..87a5f23 --- /dev/null +++ b/Print.Application/Print/EzioInterop.cs @@ -0,0 +1,302 @@ +using System; +using System.Runtime.InteropServices; + +namespace JingGong.Abp.Print.GoDEX +{ + public class EzioInterop + { + const string EzioLibrary = "ezio.so.1.1.0"; + const string Usblib = "usb-1.0.so.0"; + + /// + /// Open 函数 + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern bool Open(string hostname, int port); + + /// + /// Close 函数 + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void Close(); + + // openUSB 函数 + [DllImport(Usblib, CallingConvention = CallingConvention.Cdecl)] + public static extern int openUSB(); + + /// + /// closeUSB 函数 + /// + [DllImport(Usblib, CallingConvention = CallingConvention.Cdecl)] + public static extern void closeUSB(); + + /// + /// OpenDriver 函数 + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int OpenDriver(string port); + + /// + /// closeport 函数 + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int closeport(); + + /// + /// RcvBuf 函数 + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int RcvBuf(IntPtr buf, UIntPtr count); + + /// + /// sendbuf 函数 + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int sendbuf([MarshalAs(UnmanagedType.LPArray)] byte[] buf, int count); + + /// + /// sendcommand 函数 + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int sendcommand(string cmd); + + /// + /// setup 函数 + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int setup(int mm, int dark, int speed, int mode, int gap, int top); + + /// + /// Bar 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int Bar(string BarcodeType, int PosX, int PosY, int Narrow, int Wide, int Height, int Rotation, int Readable, string data); + + /// + /// Bar_S 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int Bar_S(string BarcodeType, int PosX, int PosY, string data); + + /// + /// Bar_QRcode 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int Bar_QRcode(int PosX, int PosY, int Mode, int Type, string ErrorLevel, int Mask, int Mul, int Len, int Rotation, string data); + + /// + /// Bar_QRcode_S 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int Bar_QRcode_S(int PosX, int PosY, int Len, string data); + + /// + /// DrawHorLine 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int DrawHorLine(int PosX, int PosY, int Length, int Thick); + + /// + /// DrawVerLine 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int DrawVerLine(int PosX, int PosY, int Length, int Thick); + + /// + /// InternalFont_TextOut 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int InternalFont_TextOut(string FontType, int PosX, int PosY, int Mul_X, int Mul_Y, int Gap, string RotationInverse, string Data); + + /// + /// InternalFont_TextOut_S 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int InternalFont_TextOut_S(string FontType, int PosX, int PosY, string Data); + + /// + /// DownloadFont_TextOut 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int DownloadFont_TextOut(string FontName, int PosX, int PosY, int Mul_X, int Mul_Y, int Gap, string RotationInverse, string Data); + + /// + /// DownloadFont_TextOut_S 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int DownloadFont_TextOut_S(string FontName, int PosX, int PosY, string Data); + + /// + /// TrueTypeFont_TextOut 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int TrueTypeFont_TextOut(string FontName, int PosX, int PosY, int Font_W, int Font_H, int SpaceChar, string RotationInverse, string TTFTable, int WidthMode, string Data); + + /// + /// TrueTypeFont_TextOut_S 函数 + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int TrueTypeFont_TextOut_S(string FontName, int PosX, int PosY, string Data); + + /// + /// ecTextOut 函数 + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int ecTextOut(int x, int y, int height, string fontname, string TEXT); + + /// + /// ecTextOutR 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int ecTextOutR(int x, int y, int height, string fontname, string TEXT, int width, int degree); + + /// + /// ecTextOutW 函数 + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int ecTextOutW(int x, int y, int height, string fontname, [MarshalAs(UnmanagedType.LPWStr)] string TEXT); + + /// + /// ecTextOutRW 函数 + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int ecTextOutRW(int x, int y, int height, string fontname, [MarshalAs(UnmanagedType.LPWStr)] string TEXT, int width, int degree); + + [DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int putimage(int x, int y, [MarshalAs(UnmanagedType.LPStr)] string Filename, int Degree); + } +} diff --git a/Print.Application/Print/GoDEXCommunication.cs b/Print.Application/Print/GoDEXCommunication.cs new file mode 100644 index 0000000..d43d42d --- /dev/null +++ b/Print.Application/Print/GoDEXCommunication.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印机配置 + /// + public class GoDEXCommunication + { + /// + /// 地址 + /// + public string Host { get; set; } + + /// + /// 端口 + /// + public int Port { get; set; } + } +} diff --git a/Print.Application/Print/GoDEXEnum.cs b/Print.Application/Print/GoDEXEnum.cs new file mode 100644 index 0000000..3ac43b1 --- /dev/null +++ b/Print.Application/Print/GoDEXEnum.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印机状态 + /// + public enum GoDEXEnum + { + 待機狀態 = 00, + 耗材用盡 = 01, + 卡紙 = 02, + 碳帶用盡 = 03, + 印表頭開啟 = 04, + 背紙回收器已滿 = 05, + 檔案系統已滿 = 06, + 找不到檔案 = 07, + 檔名重複 = 08, + 指令語法錯誤 = 09, + 裁刀卡住或未安裝裁刀 = 10, + 無延伸記憶體 = 11, + 等待取走標籤 = 13, + 暫停 = 20, + 設定模式 = 21, + 鍵盤模式 = 22, + 印表機列印中 = 50, + 資料處理中 = 60, + 印表頭過熱 = 62, + } +} diff --git a/Print.Application/Print/GoDEXPrint.cs b/Print.Application/Print/GoDEXPrint.cs new file mode 100644 index 0000000..4dfb7bb --- /dev/null +++ b/Print.Application/Print/GoDEXPrint.cs @@ -0,0 +1,131 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + public class GoDEXPrint : IDisposable + { + private static object printLock = new object(); + + + /// + /// 连接打印机 + /// + /// + public bool Open(GoDEXCommunication goDEXCommunication) + { + return EzioInterop.Open(goDEXCommunication.Host, goDEXCommunication.Port); + } + + /// + /// 关闭打印机 + /// + /// + public bool Close() + { + return EzioInterop.closeport() == 1; + } + + /// + /// 打印 + /// + /// + public bool Print(IGoDEXPrintData goDEXPrintData) + { + bool printSuccess = false; + //_logger.LogInformation("3.进入打印机方法,锁外"); + try + { + // 打印任务执行,可能是阻塞的,因此考虑异步执行 + Task.Run(() => + { + try + { + //GoDEX库因无法识别打印机,当前只适应用单任务打印 + //lock (printLock) + //{ + + if (Open(goDEXPrintData.Communication)) + { + LabelSetup(goDEXPrintData); + + //^L(標籤起始符號設定,^L 正常列印,^LI 反白列印,^LM 鏡像列印,^LRn 整張旋轉 n=0, 0°列印 ; n=1, 90°列印 ; n=2, 180°列印 ; n=3, 270°列印) + EzioInterop.sendcommand($"^L"); + // 尝试执行打印操作,成功返回 + if (goDEXPrintData.Print()) + { + printSuccess = true; + } + else + { + throw new Exception("打印失败!"); + } + //结束,打印机收到后开始打印 + EzioInterop.sendcommand("E"); + } + else + { + Console.WriteLine("6.打印机连接失败"); + throw new Exception("打印机连接失败!"); + } + + } + catch (Exception ex) + { + // 记录异常日志 + //_logger.LogInformation($"5.打印操作异常:{ex.Message}"); + Console.WriteLine($"打印操作异常:{ex.Message}"); + } + finally + { + Close(); + } + }); + } + catch(Exception ex) + { + // 捕获整个过程中的异常 + //_logger.LogInformation($"打印失败,异常:{ex.Message}"); + Console.WriteLine($"打印失败:{ex.Message}"); + } + return printSuccess; + } + + /// + /// 设定参数 + /// + /// + private void LabelSetup(IGoDEXPrintData goDEXPrintData) + { + //標籤長度設定 x长,y不指定,z每张间隔) + EzioInterop.sendcommand($"^Q{goDEXPrintData.LabelSetup.Height},0,{goDEXPrintData.LabelSetup.Speed}"); + + //^W54(標籤寬度設定) + EzioInterop.sendcommand($"^W{goDEXPrintData.LabelSetup.Width}"); + + //^H10(列印黑度設定x = 00 ~ 19) + EzioInterop.sendcommand($"^H{goDEXPrintData.LabelSetup.Dark}"); + + //^S3(列印速度設定x = 2 ~ 10) + EzioInterop.sendcommand($"^H{goDEXPrintData.LabelSetup.Speed}"); + + //^P1(連續列印) + EzioInterop.sendcommand($"^P1"); + + //^C1(複製張數x = 1 ~ 32767) + EzioInterop.sendcommand($"^C1"); + } + + /// + /// 关闭打印机 + /// + public void Dispose() + { + Close(); + } + } +} diff --git a/Print.Application/Print/GoDEXPrintBase64Image.cs b/Print.Application/Print/GoDEXPrintBase64Image.cs new file mode 100644 index 0000000..7ea5c44 --- /dev/null +++ b/Print.Application/Print/GoDEXPrintBase64Image.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 按base64打印图片 + /// + public class GoDEXPrintBase64Image : GoDEXPrintImage + { + /// + /// Base64数据 + /// + public string ImageBase64 { get; set; } + + /// + /// 获取图片数据 + /// + /// + protected override byte[] GetImageData() + { + var base64Content = ImageBase64; + // 检查是否包含 Base64 前缀 + if (base64Content.Contains("base64,")) + { + // 去除 "data:image/;base64," 头部信息 + base64Content = base64Content.Substring(base64Content.IndexOf(",") + 1); + } + + return Convert.FromBase64String(base64Content); + } + } +} diff --git a/Print.Application/Print/GoDEXPrintData.cs b/Print.Application/Print/GoDEXPrintData.cs new file mode 100644 index 0000000..4704ad7 --- /dev/null +++ b/Print.Application/Print/GoDEXPrintData.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印数据基础数据结构 + /// + public abstract class GoDEXPrintData : IGoDEXPrintData + { + public GoDEXCommunication Communication { get; set; } + + public GoDEXPrintSetup LabelSetup { get; set; } + + /// + /// 1毫米的点数 + /// + public readonly int Dots = 8; + + public abstract bool Print(); + + } +} diff --git a/Print.Application/Print/GoDEXPrintImage.cs b/Print.Application/Print/GoDEXPrintImage.cs new file mode 100644 index 0000000..7731d2b --- /dev/null +++ b/Print.Application/Print/GoDEXPrintImage.cs @@ -0,0 +1,170 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System.Collections.Generic; +using System.Text; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印图片 + /// + public abstract class GoDEXPrintImage : GoDEXPrintData + { + /// + /// X起始位置,单位mm + /// + public int PosX { get; set; } + + /// + /// Y起始位置,单位mm + /// + public int PosY { get; set; } + + /// + /// 图片宽,单位mm + /// + public int Width { get; set; } + + /// + /// 图片高,单位mm + /// + public int Height { get; set; } + + /// + /// 打印图像 + /// + /// + public override bool Print() + { + var imageData = ProcessImageData(); + + //Q10,10,102,484(圖案命令x,y,width,heigh) + //x = 自左上角量起之水平位置(單位:dots). + //y = 自左上角量起之垂直位置(單位:dots). + //width = 圖檔寬度(單位:byte) + //height = 圖檔高度(單位:dots) + EzioInterop.sendcommand($"Q{PosX * Dots},{PosY * Dots},{imageData.Width},{imageData.Height}"); + //EzioInterop.sendcommand($"Q40,10,3,8"); + + //发送图片数据 + //EzioInterop.sendcommand(imageData); + EzioInterop.sendbuf(imageData.Data, imageData.Data.Length); + //EzioInterop.sendbuf(new byte[] { 0b01000001, 0b01000001, 0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001, + //0b01000001,0b01000001,0b01000001,}, 24); + + EzioInterop.sendcommand("\n"); + + return true; + + } + + /// + /// 处理图片数据 + /// + /// + /// + protected virtual (int Width, int Height, byte[] Data) ProcessImageData() + { + var imageBytes = GetImageData(); + + // 加载图像 + using (var image = Image.Load(imageBytes)) + { + // 获取原始图像尺寸 + int originalWidth = image.Width; + int originalHeight = image.Height; + + image.Mutate(ctx => + { + // 转换为灰度图像 + // 进行二值化,128是阈值,低于该值为黑色,高于为白色 + //image.Mutate(x => x.Grayscale().BinaryThreshold(128f / 255f)); + ctx.Grayscale(); + + //调整图像大小 + if (Width != 0 || Height != 0) + ctx.Resize(originalWidth * 2, originalHeight * 2, KnownResamplers.Bicubic); + + ////适当锐化 + //ctx.GaussianSharpen(3f); + + ////调整对比度 + //ctx.Contrast(1.2f); + + }); + + return ConvertImageToBytes(image); + } + } + + /// + /// 获取图片数据 + /// + /// + protected abstract byte[] GetImageData(); + + /// + /// 获取图像数据 + /// + /// + /// + protected (int Width, int Height, byte[] Data) ConvertImageToBytes(Image image) + { + StringBuilder sb = new StringBuilder(); + + var clonedImage = image.CloneAs(); + + + // 创建一个列表来存储字节数据 + List byteList = new List(); + + // 遍历每一行 + for (int y = 0; y < image.Height; y++) + { + byte currentByte = 0; + int bitCount = 0; + + for (int x = 0; x < image.Width; x++) + { + // 获取当前像素的颜色 + var pixel = clonedImage[x, y]; + + // 黑色为1,白色为0(颠倒值) + //将灰度转为黑白,选择适当灰度值转为黑色 + byte pixelValue = pixel.R <= 180 ? (byte)1 : (byte)0; + + // 将像素值存入当前字节 + currentByte |= (byte)(pixelValue << (7 - bitCount)); + bitCount++; + + // 如果一个字节已满,保存该字节并清空 + if (bitCount == 8) + { + sb.Append((char)currentByte); + + byteList.Add(currentByte); + currentByte = 0; + bitCount = 0; + + } + } + + // 如果行末不足8个像素,则补充零 + if (bitCount > 0) + { + sb.Append((char)currentByte); + byteList.Add(currentByte); + } + } + + return (image.Width % 8 == 0 ? image.Width / 8 : image.Width / 8 + 1, image.Height, byteList.ToArray()); + } + } +} diff --git a/Print.Application/Print/GoDEXPrintImageFile.cs b/Print.Application/Print/GoDEXPrintImageFile.cs new file mode 100644 index 0000000..62d0a5c --- /dev/null +++ b/Print.Application/Print/GoDEXPrintImageFile.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 按图片打印 + /// + public class GoDEXPrintImageFile : GoDEXPrintImage + { + /// + /// 图片地址 + /// + public string FilePath { get; set; } + + /// + /// 获取图片数据 + /// + /// + protected override byte[] GetImageData() + { + return File.ReadAllBytes(FilePath); + } + } +} diff --git a/Print.Application/Print/GoDEXPrintSetup.cs b/Print.Application/Print/GoDEXPrintSetup.cs new file mode 100644 index 0000000..4807666 --- /dev/null +++ b/Print.Application/Print/GoDEXPrintSetup.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印页面配置 + /// + public class GoDEXPrintSetup + { + /// + /// 高 + /// + public int Height { get; set; } + + /// + /// 宽 + /// + public int Width { get; set; } + + /// + /// 间隔 + /// + public int Speed { get; set; } + + /// + /// 黑度 + /// + public int Dark { get; set; } + } +} diff --git a/Print.Application/Print/IGoDEXPrintData.cs b/Print.Application/Print/IGoDEXPrintData.cs new file mode 100644 index 0000000..1966d7e --- /dev/null +++ b/Print.Application/Print/IGoDEXPrintData.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JingGong.Abp.Print.GoDEX +{ + /// + /// 打印数据接口 + /// + public interface IGoDEXPrintData + { + GoDEXCommunication Communication { get; set; } + + GoDEXPrintSetup LabelSetup { get; set; } + + abstract bool Print(); + } +} diff --git a/Print.Application/Print/PrintExtension.cs b/Print.Application/Print/PrintExtension.cs new file mode 100644 index 0000000..5d3b3a9 --- /dev/null +++ b/Print.Application/Print/PrintExtension.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Builder; +using System; +using System.IO; +using System.Reflection; + +namespace JingGong.Abp.Print.GoDEX +{ + public static class PrintExtension + { + public static void AddGoDEX(this IApplicationBuilder applicationBuilder) + { + //注:docker运行时需添加环境变量:#ENV LD_LIBRARY_PATH=/app/libx64:$LD_LIBRARY_PATH + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libezio.so.1.1.0", "libx64/libezio.so.1.1.0"); + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libttf_x64.so", "libx64/libttf_x64.so"); + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libusb-1.0.so.0.3.0", "libx64/libusb-1.0.so.0"); + + //临时解决环境变量未生效问题 + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libezio.so.1.1.0", "libezio.so.1.1.0"); + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libttf_x64.so", "libttf_x64.so"); + ExtractResourceToFile("JingGong.Abp.Print.GoDEX.x64lib.libusb-1.0.so.0.3.0", "libusb-1.0.so.0"); + } + + /// + /// 释放资源文件至本地文件 + /// + /// + /// + internal static void ExtractResourceToFile(string resourceName, string fileFullName) + { + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) + { + if (stream == null) + return; + + try + { + var dir = Path.GetDirectoryName(fileFullName); + + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + using (FileStream fileStream = new FileStream(fileFullName, FileMode.Create, FileAccess.Write)) + { + stream.CopyTo(fileStream); + } + } + catch + { + Console.WriteLine($"写入{fileFullName}失败"); + } + } + } + } +} diff --git a/Print.Application/Print/x64lib/libezio.so.1.1.0 b/Print.Application/Print/x64lib/libezio.so.1.1.0 new file mode 100644 index 0000000..aa567a6 Binary files /dev/null and b/Print.Application/Print/x64lib/libezio.so.1.1.0 differ diff --git a/Print.Application/Print/x64lib/libttf_x64.so b/Print.Application/Print/x64lib/libttf_x64.so new file mode 100644 index 0000000..0969704 Binary files /dev/null and b/Print.Application/Print/x64lib/libttf_x64.so differ diff --git a/Print.Application/Print/x64lib/libusb-1.0.so.0.3.0 b/Print.Application/Print/x64lib/libusb-1.0.so.0.3.0 new file mode 100644 index 0000000..c3810be Binary files /dev/null and b/Print.Application/Print/x64lib/libusb-1.0.so.0.3.0 differ diff --git a/Print.Forum.Application.Contracts/ForumApplicationContractsModule.cs b/Print.Forum.Application.Contracts/ForumApplicationContractsModule.cs new file mode 100644 index 0000000..0e9318a --- /dev/null +++ b/Print.Forum.Application.Contracts/ForumApplicationContractsModule.cs @@ -0,0 +1,7 @@ +using Volo.Abp.Modularity; + +namespace Print.Forum.Application.Contracts; + +public class ForumApplicationContractsModule : AbpModule +{ +} \ No newline at end of file diff --git a/Print.Forum.Application.Contracts/Print.Forum.Application.Contracts.csproj b/Print.Forum.Application.Contracts/Print.Forum.Application.Contracts.csproj new file mode 100644 index 0000000..64c4ccd --- /dev/null +++ b/Print.Forum.Application.Contracts/Print.Forum.Application.Contracts.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Print.Forum.Application.Contracts/PrintPictureDto.cs b/Print.Forum.Application.Contracts/PrintPictureDto.cs new file mode 100644 index 0000000..7e177f5 --- /dev/null +++ b/Print.Forum.Application.Contracts/PrintPictureDto.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Print.Forum.Application.Contracts +{ + public class PrintPictureDto + { + /// + /// 线体编码 + /// + public string LineCode { get; set; } + /// + /// 租户名称 + /// + public string TenantName { get; set; } + public List Base64Data { get; set; } + public string ip { get; set; } + } +} diff --git a/Print.Forum.Application.Contracts/ResultDto.cs b/Print.Forum.Application.Contracts/ResultDto.cs new file mode 100644 index 0000000..0feee58 --- /dev/null +++ b/Print.Forum.Application.Contracts/ResultDto.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Print.Forum.Application.Contracts +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Text; + + namespace JingGong.Abp.MES + { + public class CommonDto + { + } + + + + public class SelectOptionDto + { + /// + /// 选项类型id + /// + [Description("选项类型id")] + public string Option_Id + { + get; set; + } + /// + /// 选项类型名称 + /// + [Description("选项类型名称")] + public string Option_Name { get; set; } + + + /// + /// 选项扩展 + /// + [Description("选项扩展")] + public string Option_Extend { get; set; } + + } + public class ExecResult + { + + public string ErrorMessage { get; set; } + public bool IsScucess { get; set; } + public int ReturnCode { get; set; } + } + + + /// + /// 通用的操作方法返回类(不携带数据) + /// + [Serializable] + public class ResultDto + { + /// + /// 操作是否成功 + /// + [Description("操作是否成功")] + public bool IsSuccess { get; set; } + + /// + /// 操作提示语 + /// + [Description("操作提示语")] + public string Info { get; set; } + + /// + /// 错误列表 + /// + [Description("错误列表")] + public List ErrorList { get; set; } + + /// + /// 以是否成功和提示语进行初始化 + /// + /// 是否成功 + /// 提示语 + /// 辅助对象 + public ResultDto(bool isSuccess, string info = "") + { + this.IsSuccess = isSuccess; + this.Info = info; + } + /// + /// 用于if语句,直接判断是否成功 + /// + /// + /// + public static implicit operator Boolean(ResultDto t) + { + if (t == null) + { + return false; + } + return t.IsSuccess; + } + } + + /// + /// 通用的操作方法返回类(携带泛型数据) + /// + /// + public class ResultDto : ResultDto + { + /// + /// 携带的辅助对象 + /// + public T Data { get; set; } + + /// + /// 以操作是否成功、提示语、携带数据进行初始化 + /// + /// 是否成功 + /// 提示语 + /// 辅助对象 + public ResultDto(bool isSuccess, string info = "", T data = default(T)) : base(isSuccess, info) + { + this.Data = data; + } + + public ResultDto(ResultDto result) : base(result.IsSuccess, result.Info) + { + this.Data = default(T); + } + + /// + /// 默认构造方法 + /// + public ResultDto() : base(false, string.Empty) + { } + } + } + +} diff --git a/Print.Forum.Domain/ForumDomainModule.cs b/Print.Forum.Domain/ForumDomainModule.cs new file mode 100644 index 0000000..25ed2b1 --- /dev/null +++ b/Print.Forum.Domain/ForumDomainModule.cs @@ -0,0 +1,7 @@ +using Volo.Abp.Modularity; + +namespace Print.Forum.Domain; + +public class ForumDomainModule : AbpModule +{ +} diff --git a/Print.Forum.Domain/Print.Forum.Domain.csproj b/Print.Forum.Domain/Print.Forum.Domain.csproj new file mode 100644 index 0000000..4d59c92 --- /dev/null +++ b/Print.Forum.Domain/Print.Forum.Domain.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Print.Forum.HttpApi.Host/Dockerfile b/Print.Forum.HttpApi.Host/Dockerfile new file mode 100644 index 0000000..6c43bff --- /dev/null +++ b/Print.Forum.HttpApi.Host/Dockerfile @@ -0,0 +1,27 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.csproj", "Print.Forum.HttpApi.Host/"] +COPY ["Print.Application/Print.Application.csproj", "Print.Application/"] +COPY ["Print.Forum.Application.Contracts/Print.Forum.Application.Contracts.csproj", "Print.Forum.Application.Contracts/"] +RUN dotnet restore "./Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.csproj" +COPY . . +WORKDIR "/src/Print.Forum.HttpApi.Host" +RUN dotnet build "./Print.Forum.HttpApi.Host.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Print.Forum.HttpApi.Host.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Print.Forum.HttpApi.Host.dll"] \ No newline at end of file diff --git a/Print.Forum.HttpApi.Host/ForumHttpApiHostModule.cs b/Print.Forum.HttpApi.Host/ForumHttpApiHostModule.cs new file mode 100644 index 0000000..5ee2219 --- /dev/null +++ b/Print.Forum.HttpApi.Host/ForumHttpApiHostModule.cs @@ -0,0 +1,73 @@ +using Print.Application; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; + +namespace Print.Forum.HttpApi.Host +{ + + [DependsOn(typeof(AbpAspNetCoreMvcModule), typeof(AbpAutofacModule))] + [DependsOn(typeof(ForumApplicationModule) + )] + public class ForumHttpApiHostModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var services = context.Services; + var configuration = services.GetConfiguration(); + + // 跨域 + context.Services.AddCors(options => + { + options.AddPolicy("AllowAll", builder => + { + builder.AllowAnyOrigin() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod(); + }); + }); + + // 自动生成控制器 + Configure(options => + { + options.ConventionalControllers.Create(typeof(ForumApplicationModule).Assembly); + }); + + // swagger + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo() + { + Title = "ForumApi", + Version = "v0.1" + }); + options.DocInclusionPredicate((docName, predicate) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var env = context.GetEnvironment(); + var app = context.GetApplicationBuilder(); + var configuration = context.GetConfiguration(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseCors("AllowAll"); + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "ForumApi"); + }); + + app.UseRouting(); + app.UseConfiguredEndpoints(); + } + } +} diff --git a/Print.Forum.HttpApi.Host/GoDEXPrintController.cs b/Print.Forum.HttpApi.Host/GoDEXPrintController.cs new file mode 100644 index 0000000..8db2fa7 --- /dev/null +++ b/Print.Forum.HttpApi.Host/GoDEXPrintController.cs @@ -0,0 +1,132 @@ +using Microsoft.AspNetCore.Mvc; +using Print.Application; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.MultiTenancy; +using Volo.Abp; +using Print.Forum.Application.Contracts.JingGong.Abp.MES; +using Print.Forum.Application.Contracts; +using Newtonsoft.Json; + +namespace Print.Forum.HttpApi.Host +{ + /// + /// 打印实现 + /// + [RemoteService] + [Area("Print")] + [Route("api/MES/[Controller]")] + public class GoDEXPrintController : AbpController + { + private readonly ILogger _logger; + + + /// + /// 构造方法 + /// + /// + public GoDEXPrintController(ILogger logger, ICurrentTenant currentTenant) + { + _logger = logger; + } + + /// + /// 打印图片文件 + /// + /// + /// + [HttpPost] + [Route("PrintImageFile")] + public ResultDto PrintImageFile(GoDEXPrintImageFile goDEXPrintImageFile) + { + if (goDEXPrintImageFile == null) + return new ResultDto(false, $"参数{nameof(goDEXPrintImageFile)}不可为空!"); + + try + { + var godex = new GoDEXPrint(); + + godex.Print(goDEXPrintImageFile); + + return new ResultDto(true); + } + catch (Exception ex) + { + _logger.LogError(ex, $"打印失败:{goDEXPrintImageFile}"); + + return new ResultDto(false, $"打印失败:{nameof(ex.Message)}"); + } + } + + /// + /// 打印base64格式图片 + /// + /// + /// + [HttpPost] + [Route("PrintBase64Image")] + public ResultDto PrintBase64Image(GoDEXPrintBase64Image goDEXPrintBase64Image) + { + if (goDEXPrintBase64Image == null) + return new ResultDto(false, $"参数{nameof(goDEXPrintBase64Image)}不可为空!"); + + try + { + var godex = new GoDEXPrint(); + + godex.Print(goDEXPrintBase64Image); + + return new ResultDto(true); + } + catch (Exception ex) + { + + return new ResultDto(false, $"打印失败:{nameof(ex.Message)}"); + } + } + + [HttpPost] + [Route("PrintBase64Imagenew")] + public async Task PrintBase64Imagenew(PrintPictureDto input) + { + _logger.LogInformation("1.进入打印接口"); + //切换业务所属的租户 + + GoDEXPrintBase64Image goDEXPrintBase64Image = new GoDEXPrintBase64Image(); + goDEXPrintBase64Image.Communication = new GoDEXCommunication(); + goDEXPrintBase64Image.Communication.Host = input.ip; + goDEXPrintBase64Image.Communication.Port = 9100; + goDEXPrintBase64Image.LabelSetup = new GoDEXPrintSetup(); + goDEXPrintBase64Image.LabelSetup.Height = 70; + goDEXPrintBase64Image.LabelSetup.Speed = 3; + goDEXPrintBase64Image.LabelSetup.Width = 100; + goDEXPrintBase64Image.LabelSetup.Dark = 10; + goDEXPrintBase64Image.PosX = 3; + goDEXPrintBase64Image.PosY = 3; + goDEXPrintBase64Image.Width = 97; + goDEXPrintBase64Image.Height = 67; + goDEXPrintBase64Image.ImageBase64 = input.Base64Data.First(); + + if (goDEXPrintBase64Image == null) + return new ResultDto(false, $"参数{nameof(goDEXPrintBase64Image)}不可为空!"); + + try + { + var godex = new GoDEXPrint(); + + godex.Print(goDEXPrintBase64Image); + + return new ResultDto(true); + } + catch (Exception ex) + { + _logger.LogError(ex, $"打印失败:{JsonConvert.SerializeObject(goDEXPrintBase64Image)}"); + + return new ResultDto(false, $"打印失败:{nameof(ex.Message)}"); + } + return new ResultDto(false, ""); + + } + + } +} diff --git a/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.csproj b/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.csproj new file mode 100644 index 0000000..7d09db0 --- /dev/null +++ b/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + be372b4a-f87d-477c-bf6d-7468c93527cd + Linux + + + + + + + + + + + + + + + + + diff --git a/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.http b/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.http new file mode 100644 index 0000000..806d365 --- /dev/null +++ b/Print.Forum.HttpApi.Host/Print.Forum.HttpApi.Host.http @@ -0,0 +1,6 @@ +@Print.Forum.HttpApi.Host_HostAddress = http://localhost:5090 + +GET {{Print.Forum.HttpApi.Host_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Print.Forum.HttpApi.Host/Program.cs b/Print.Forum.HttpApi.Host/Program.cs new file mode 100644 index 0000000..9a12d34 --- /dev/null +++ b/Print.Forum.HttpApi.Host/Program.cs @@ -0,0 +1,30 @@ +using Print.Forum.HttpApi.Host; +using Serilog.Events; +using Serilog; + +Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("logs/logs.log")) +#if DEBUG + .WriteTo.Async(c => c.Console()) +#endif + .CreateLogger(); + +var builder = WebApplication.CreateBuilder(args); +builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); +// Add services to the container. +await builder.AddApplicationAsync(); + +var app = builder.Build(); +// Configure the HTTP request pipeline. +await app.InitializeApplicationAsync(); +await app.RunAsync(); \ No newline at end of file diff --git a/Print.Forum.HttpApi.Host/Properties/launchSettings.json b/Print.Forum.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..c915a46 --- /dev/null +++ b/Print.Forum.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5090" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7005;http://localhost:5090" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:20399", + "sslPort": 44333 + } + } +} \ No newline at end of file diff --git a/Print.Forum.HttpApi.Host/appsettings.Development.json b/Print.Forum.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Print.Forum.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Print.Forum.HttpApi.Host/appsettings.json b/Print.Forum.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Print.Forum.HttpApi.Host/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/abp.PrintService.sln b/abp.PrintService.sln new file mode 100644 index 0000000..ebe3a63 --- /dev/null +++ b/abp.PrintService.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Print.Application", "Print.Application\Print.Application.csproj", "{74123FF3-7BDE-4D64-86FA-EB03E825DCFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Print.Forum.Domain", "Print.Forum.Domain\Print.Forum.Domain.csproj", "{0AD63448-75CE-45C0-89FC-0EC74FE117CD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Print.Forum.Application.Contracts", "Print.Forum.Application.Contracts\Print.Forum.Application.Contracts.csproj", "{CB17DC96-5C34-438E-892D-6AC40B80D1EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Print.Forum.HttpApi.Host", "Print.Forum.HttpApi.Host\Print.Forum.HttpApi.Host.csproj", "{F7289495-78F1-4085-AEA7-5DD0E877BB7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {74123FF3-7BDE-4D64-86FA-EB03E825DCFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74123FF3-7BDE-4D64-86FA-EB03E825DCFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74123FF3-7BDE-4D64-86FA-EB03E825DCFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74123FF3-7BDE-4D64-86FA-EB03E825DCFE}.Release|Any CPU.Build.0 = Release|Any CPU + {0AD63448-75CE-45C0-89FC-0EC74FE117CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AD63448-75CE-45C0-89FC-0EC74FE117CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AD63448-75CE-45C0-89FC-0EC74FE117CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AD63448-75CE-45C0-89FC-0EC74FE117CD}.Release|Any CPU.Build.0 = Release|Any CPU + {CB17DC96-5C34-438E-892D-6AC40B80D1EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB17DC96-5C34-438E-892D-6AC40B80D1EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB17DC96-5C34-438E-892D-6AC40B80D1EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB17DC96-5C34-438E-892D-6AC40B80D1EF}.Release|Any CPU.Build.0 = Release|Any CPU + {F7289495-78F1-4085-AEA7-5DD0E877BB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7289495-78F1-4085-AEA7-5DD0E877BB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7289495-78F1-4085-AEA7-5DD0E877BB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7289495-78F1-4085-AEA7-5DD0E877BB7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/新建 文本文档.md b/新建 文本文档.md new file mode 100644 index 0000000..e69de29