添加项目文件。

This commit is contained in:
李捷
2025-07-12 16:20:14 +08:00
parent 67f108002e
commit fa5bf23c08
35 changed files with 1574 additions and 0 deletions

30
.dockerignore Normal file
View File

@ -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/**

View File

@ -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()
{
}
}
}

View File

@ -0,0 +1,34 @@
using Microsoft.Extensions.DependencyInjection;
using Print.Forum.Application.Contracts;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
namespace Print.Application;
/// <summary>
/// 项目模块依赖、组件依赖
/// </summary>
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(ForumApplicationContractsModule)
)]
public class ForumApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var services = context.Services;
// 添加ObjectMapper注入
services.AddAutoMapperObjectMapper<ForumApplicationModule>();
// Abp AutoMapper设置
Configure<AbpAutoMapperOptions>(config =>
{
// 添加对应依赖关系Profile
config.AddMaps<ForumApplicationAutoMapperProfile>();
});
}
}

View File

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.10" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="8.1.1" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="8.1.1" />
</ItemGroup>
<ItemGroup>
<None Remove="Print\x64lib\libezio.so.1.1.0" />
<None Remove="Print\x64lib\libttf_x64.so" />
<None Remove="Print\x64lib\libusb-1.0.so.0.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Print.Forum.Application.Contracts\Print.Forum.Application.Contracts.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Print\" />
</ItemGroup>
</Project>

View File

@ -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";
/// <summary>
/// Open 函数
/// </summary>
/// <param name="hostname"></param>
/// <param name="port"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern bool Open(string hostname, int port);
/// <summary>
/// Close 函数
/// </summary>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern void Close();
// openUSB 函数
[DllImport(Usblib, CallingConvention = CallingConvention.Cdecl)]
public static extern int openUSB();
/// <summary>
/// closeUSB 函数
/// </summary>
[DllImport(Usblib, CallingConvention = CallingConvention.Cdecl)]
public static extern void closeUSB();
/// <summary>
/// OpenDriver 函数
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int OpenDriver(string port);
/// <summary>
/// closeport 函数
/// </summary>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int closeport();
/// <summary>
/// RcvBuf 函数
/// </summary>
/// <param name="buf"></param>
/// <param name="count"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int RcvBuf(IntPtr buf, UIntPtr count);
/// <summary>
/// sendbuf 函数
/// </summary>
/// <param name="buf"></param>
/// <param name="count"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int sendbuf([MarshalAs(UnmanagedType.LPArray)] byte[] buf, int count);
/// <summary>
/// sendcommand 函数
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int sendcommand(string cmd);
/// <summary>
/// setup 函数
/// </summary>
/// <param name="mm"></param>
/// <param name="dark"></param>
/// <param name="speed"></param>
/// <param name="mode"></param>
/// <param name="gap"></param>
/// <param name="top"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int setup(int mm, int dark, int speed, int mode, int gap, int top);
/// <summary>
/// Bar 函数
/// </summary>
/// <param name="BarcodeType"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Narrow"></param>
/// <param name="Wide"></param>
/// <param name="Height"></param>
/// <param name="Rotation"></param>
/// <param name="Readable"></param>
/// <param name="data"></param>
/// <returns></returns>
[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);
/// <summary>
/// Bar_S 函数
/// </summary>
/// <param name="BarcodeType"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="data"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int Bar_S(string BarcodeType, int PosX, int PosY, string data);
/// <summary>
/// Bar_QRcode 函数
/// </summary>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Mode"></param>
/// <param name="Type"></param>
/// <param name="ErrorLevel"></param>
/// <param name="Mask"></param>
/// <param name="Mul"></param>
/// <param name="Len"></param>
/// <param name="Rotation"></param>
/// <param name="data"></param>
/// <returns></returns>
[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);
/// <summary>
/// Bar_QRcode_S 函数
/// </summary>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Len"></param>
/// <param name="data"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int Bar_QRcode_S(int PosX, int PosY, int Len, string data);
/// <summary>
/// DrawHorLine 函数
/// </summary>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Length"></param>
/// <param name="Thick"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int DrawHorLine(int PosX, int PosY, int Length, int Thick);
/// <summary>
/// DrawVerLine 函数
/// </summary>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Length"></param>
/// <param name="Thick"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int DrawVerLine(int PosX, int PosY, int Length, int Thick);
/// <summary>
/// InternalFont_TextOut 函数
/// </summary>
/// <param name="FontType"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Mul_X"></param>
/// <param name="Mul_Y"></param>
/// <param name="Gap"></param>
/// <param name="RotationInverse"></param>
/// <param name="Data"></param>
/// <returns></returns>
[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);
/// <summary>
/// InternalFont_TextOut_S 函数
/// </summary>
/// <param name="FontType"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Data"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int InternalFont_TextOut_S(string FontType, int PosX, int PosY, string Data);
/// <summary>
/// DownloadFont_TextOut 函数
/// </summary>
/// <param name="FontName"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Mul_X"></param>
/// <param name="Mul_Y"></param>
/// <param name="Gap"></param>
/// <param name="RotationInverse"></param>
/// <param name="Data"></param>
/// <returns></returns>
[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);
/// <summary>
/// DownloadFont_TextOut_S 函数
/// </summary>
/// <param name="FontName"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Data"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int DownloadFont_TextOut_S(string FontName, int PosX, int PosY, string Data);
/// <summary>
/// TrueTypeFont_TextOut 函数
/// </summary>
/// <param name="FontName"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Font_W"></param>
/// <param name="Font_H"></param>
/// <param name="SpaceChar"></param>
/// <param name="RotationInverse"></param>
/// <param name="TTFTable"></param>
/// <param name="WidthMode"></param>
/// <param name="Data"></param>
/// <returns></returns>
[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);
/// <summary>
/// TrueTypeFont_TextOut_S 函数
/// </summary>
/// <param name="FontName"></param>
/// <param name="PosX"></param>
/// <param name="PosY"></param>
/// <param name="Data"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int TrueTypeFont_TextOut_S(string FontName, int PosX, int PosY, string Data);
/// <summary>
/// ecTextOut 函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="height"></param>
/// <param name="fontname"></param>
/// <param name="TEXT"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int ecTextOut(int x, int y, int height, string fontname, string TEXT);
/// <summary>
/// ecTextOutR 函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="height"></param>
/// <param name="fontname"></param>
/// <param name="TEXT"></param>
/// <param name="width"></param>
/// <param name="degree"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int ecTextOutR(int x, int y, int height, string fontname, string TEXT, int width, int degree);
/// <summary>
/// ecTextOutW 函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="height"></param>
/// <param name="fontname"></param>
/// <param name="TEXT"></param>
/// <returns></returns>
[DllImport(EzioLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int ecTextOutW(int x, int y, int height, string fontname, [MarshalAs(UnmanagedType.LPWStr)] string TEXT);
/// <summary>
/// ecTextOutRW 函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="height"></param>
/// <param name="fontname"></param>
/// <param name="TEXT"></param>
/// <param name="width"></param>
/// <param name="degree"></param>
/// <returns></returns>
[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);
}
}

View File

@ -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
{
/// <summary>
/// 打印机配置
/// </summary>
public class GoDEXCommunication
{
/// <summary>
/// 地址
/// </summary>
public string Host { get; set; }
/// <summary>
/// 端口
/// </summary>
public int Port { get; set; }
}
}

View File

@ -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
{
/// <summary>
/// 打印机状态
/// </summary>
public enum GoDEXEnum
{
= 00,
= 01,
= 02,
= 03,
= 04,
滿 = 05,
滿 = 06,
= 07,
= 08,
= 09,
= 10,
= 11,
= 13,
= 20,
= 21,
= 22,
= 50,
= 60,
= 62,
}
}

View File

@ -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();
/// <summary>
/// 连接打印机
/// </summary>
/// <returns></returns>
public bool Open(GoDEXCommunication goDEXCommunication)
{
return EzioInterop.Open(goDEXCommunication.Host, goDEXCommunication.Port);
}
/// <summary>
/// 关闭打印机
/// </summary>
/// <returns></returns>
public bool Close()
{
return EzioInterop.closeport() == 1;
}
/// <summary>
/// 打印
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 设定参数
/// </summary>
/// <param name="goDEXPrintData"></param>
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");
}
/// <summary>
/// 关闭打印机
/// </summary>
public void Dispose()
{
Close();
}
}
}

View File

@ -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
{
/// <summary>
/// 按base64打印图片
/// </summary>
public class GoDEXPrintBase64Image : GoDEXPrintImage
{
/// <summary>
/// Base64数据
/// </summary>
public string ImageBase64 { get; set; }
/// <summary>
/// 获取图片数据
/// </summary>
/// <returns></returns>
protected override byte[] GetImageData()
{
var base64Content = ImageBase64;
// 检查是否包含 Base64 前缀
if (base64Content.Contains("base64,"))
{
// 去除 "data:image/<format>;base64," 头部信息
base64Content = base64Content.Substring(base64Content.IndexOf(",") + 1);
}
return Convert.FromBase64String(base64Content);
}
}
}

View File

@ -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
{
/// <summary>
/// 打印数据基础数据结构
/// </summary>
public abstract class GoDEXPrintData : IGoDEXPrintData
{
public GoDEXCommunication Communication { get; set; }
public GoDEXPrintSetup LabelSetup { get; set; }
/// <summary>
/// 1毫米的点数
/// </summary>
public readonly int Dots = 8;
public abstract bool Print();
}
}

View File

@ -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
{
/// <summary>
/// 打印图片
/// </summary>
public abstract class GoDEXPrintImage : GoDEXPrintData
{
/// <summary>
/// X起始位置单位mm
/// </summary>
public int PosX { get; set; }
/// <summary>
/// Y起始位置单位mm
/// </summary>
public int PosY { get; set; }
/// <summary>
/// 图片宽单位mm
/// </summary>
public int Width { get; set; }
/// <summary>
/// 图片高单位mm
/// </summary>
public int Height { get; set; }
/// <summary>
/// 打印图像
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 处理图片数据
/// </summary>
/// <param name="base64"></param>
/// <returns></returns>
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);
}
}
/// <summary>
/// 获取图片数据
/// </summary>
/// <returns></returns>
protected abstract byte[] GetImageData();
/// <summary>
/// 获取图像数据
/// </summary>
/// <param name="imageBytes"></param>
/// <returns></returns>
protected (int Width, int Height, byte[] Data) ConvertImageToBytes(Image image)
{
StringBuilder sb = new StringBuilder();
var clonedImage = image.CloneAs<Rgba32>();
// 创建一个列表来存储字节数据
List<byte> byteList = new List<byte>();
// 遍历每一行
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());
}
}
}

View File

@ -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
{
/// <summary>
/// 按图片打印
/// </summary>
public class GoDEXPrintImageFile : GoDEXPrintImage
{
/// <summary>
/// 图片地址
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 获取图片数据
/// </summary>
/// <returns></returns>
protected override byte[] GetImageData()
{
return File.ReadAllBytes(FilePath);
}
}
}

View File

@ -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
{
/// <summary>
/// 打印页面配置
/// </summary>
public class GoDEXPrintSetup
{
/// <summary>
/// 高
/// </summary>
public int Height { get; set; }
/// <summary>
/// 宽
/// </summary>
public int Width { get; set; }
/// <summary>
/// 间隔
/// </summary>
public int Speed { get; set; }
/// <summary>
/// 黑度
/// </summary>
public int Dark { get; set; }
}
}

View File

@ -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
{
/// <summary>
/// 打印数据接口
/// </summary>
public interface IGoDEXPrintData
{
GoDEXCommunication Communication { get; set; }
GoDEXPrintSetup LabelSetup { get; set; }
abstract bool Print();
}
}

View File

@ -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");
}
/// <summary>
/// 释放资源文件至本地文件
/// </summary>
/// <param name="resourceName"></param>
/// <param name="fileFullName"></param>
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}失败");
}
}
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,7 @@
using Volo.Abp.Modularity;
namespace Print.Forum.Application.Contracts;
public class ForumApplicationContractsModule : AbpModule
{
}

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="8.1.1" />
</ItemGroup>
</Project>

View File

@ -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
{
/// <summary>
/// 线体编码
/// </summary>
public string LineCode { get; set; }
/// <summary>
/// 租户名称
/// </summary>
public string TenantName { get; set; }
public List<string> Base64Data { get; set; }
public string ip { get; set; }
}
}

View File

@ -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
{
/// <summary>
/// 选项类型id
/// </summary>
[Description("选项类型id")]
public string Option_Id
{
get; set;
}
/// <summary>
/// 选项类型名称
/// </summary>
[Description("选项类型名称")]
public string Option_Name { get; set; }
/// <summary>
/// 选项扩展
/// </summary>
[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; }
}
/// <summary>
/// 通用的操作方法返回类(不携带数据)
/// </summary>
[Serializable]
public class ResultDto
{
/// <summary>
/// 操作是否成功
/// </summary>
[Description("操作是否成功")]
public bool IsSuccess { get; set; }
/// <summary>
/// 操作提示语
/// </summary>
[Description("操作提示语")]
public string Info { get; set; }
/// <summary>
/// 错误列表
/// </summary>
[Description("错误列表")]
public List<string> ErrorList { get; set; }
/// <summary>
/// 以是否成功和提示语进行初始化
/// </summary>
/// <param name="isSuccess">是否成功</param>
/// <param name="info">提示语</param>
/// <param name="data">辅助对象</param>
public ResultDto(bool isSuccess, string info = "")
{
this.IsSuccess = isSuccess;
this.Info = info;
}
/// <summary>
/// 用于if语句直接判断是否成功
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static implicit operator Boolean(ResultDto t)
{
if (t == null)
{
return false;
}
return t.IsSuccess;
}
}
/// <summary>
/// 通用的操作方法返回类(携带泛型数据)
/// </summary>
/// <typeparam name="T"></typeparam>
public class ResultDto<T> : ResultDto
{
/// <summary>
/// 携带的辅助对象
/// </summary>
public T Data { get; set; }
/// <summary>
/// 以操作是否成功、提示语、携带数据进行初始化
/// </summary>
/// <param name="isSuccess">是否成功</param>
/// <param name="info">提示语</param>
/// <param name="data">辅助对象</param>
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);
}
/// <summary>
/// 默认构造方法
/// </summary>
public ResultDto() : base(false, string.Empty)
{ }
}
}
}

View File

@ -0,0 +1,7 @@
using Volo.Abp.Modularity;
namespace Print.Forum.Domain;
public class ForumDomainModule : AbpModule
{
}

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.1.1" />
</ItemGroup>
</Project>

View File

@ -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"]

View File

@ -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<AbpAspNetCoreMvcOptions>(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();
}
}
}

View File

@ -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
{
/// <summary>
/// 打印实现
/// </summary>
[RemoteService]
[Area("Print")]
[Route("api/MES/[Controller]")]
public class GoDEXPrintController : AbpController
{
private readonly ILogger<GoDEXPrintController> _logger;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="logger"></param>
public GoDEXPrintController(ILogger<GoDEXPrintController> logger, ICurrentTenant currentTenant)
{
_logger = logger;
}
/// <summary>
/// 打印图片文件
/// </summary>
/// <param name="goDEXPrintImageFile"></param>
/// <returns></returns>
[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)}");
}
}
/// <summary>
/// 打印base64格式图片
/// </summary>
/// <param name="goDEXPrintBase64Image"></param>
/// <returns></returns>
[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<ResultDto> 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, "");
}
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>be372b4a-f87d-477c-bf6d-7468c93527cd</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.6" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="8.1.1" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Print.Application\Print.Application.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
@Print.Forum.HttpApi.Host_HostAddress = http://localhost:5090
GET {{Print.Forum.HttpApi.Host_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -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<ForumHttpApiHostModule>();
var app = builder.Build();
// Configure the HTTP request pipeline.
await app.InitializeApplicationAsync();
await app.RunAsync();

View File

@ -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
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

40
abp.PrintService.sln Normal file
View File

@ -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

0
新建 文本文档.md Normal file
View File