This commit is contained in:
强 杨 2024-05-21 17:51:10 +08:00
parent b5a5ffeaa3
commit 2e2ab7edd1
18 changed files with 834 additions and 43 deletions

View File

@ -0,0 +1,107 @@
name: 部署开发环境
on:
push:
branches:
- develop
env:
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.ocr.service
PROJECT_NAME: Marking.OCR.Service
PUBLISH_PATH: marking.ocr.service
PUBLISH_HOST: 192.168.2.9
PUBLISH_PORT: 22
PUBLISH_REPLICAS: 1 #启动副本数量
ASPNETCORE_ENVIRONMENT: Development
jobs:
job1:
name: 编译发布
runs-on: linux-amd
steps:
- name: 下载源码
uses: actions/checkout@v3
- name: 使用缓存
uses: actions/cache@master
with:
cache_type: nuget
mount: |
nuget
- name: 编译后端项目
uses: actions/aspnet@8.0
with:
project_name: ${{ env.PROJECT_NAME }}
- name: 打包上传镜像
uses: actions/docker@master
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
image: ${{ env.IMAGE_NAME }}
context: publish
tags: latest,${{ gitea.ref_name }}
- name: 生成环境变量文件
env:
env_file: |
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
OWNER=${{ gitea.repository_owner }}
TAG=${{ gitea.ref_name }}
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
REPLICAS=${{ env.PUBLISH_REPLICAS }}
run: |
echo "$env_file">.env
- name: 复制发布脚本
uses: docker://appleboy/drone-scp
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
target: ${{ env.PUBLISH_PATH }}
source: docker-swarm.yaml,.env
- name: 部署到服务器
uses: docker://appleboy/drone-ssh
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
script: |
if docker service ls | grep -q marking-admin-api; then
docker service rm marking-admin-api
fi
cd ${{ env.PUBLISH_PATH }}
[ -f .env ] && export $(sed '/^#/d' .env)
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
- name: 发送构建通知
if: ${{ always() }}
uses: actions/webhook@master
with:
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
content_type: application/json
template: |
{
"msgtype": "markdown",
"markdown": {
"title":"项目部署通知",
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
>**构建结果**: ${{ job.status }}
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
>**代码分支**: ${{ gitea.ref_name }}
>**提交标识**: ${{ gitea.sha }}
>**提交发起**: ${{ gitea.actor }}
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
"
}
}

View File

@ -0,0 +1,124 @@
name: 部署生产环境
on:
push:
branches:
- master
env:
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
PROJECT_NAME: src/Marking.Admin.Entry
PUBLISH_PATH: marking.admin.api
PUBLISH_HOST: 10.255.255.146,10.255.255.74
PUBLISH_PORT: 10022
PUBLISH_REPLICAS: 2 #启动副本数量
ASPNETCORE_ENVIRONMENT: Production
jobs:
release:
name: 发布版本
runs-on: linux
outputs:
version: ${{ steps.publish_version.outputs.version }}
steps:
- name: 下载源码
uses: actions/checkout@v3
- name: 发布版本
id: publish_version
uses: actions/auto-release@master
job1:
name: 编译发布
runs-on: linux-amd
needs: release
steps:
- name: 下载源码
uses: actions/checkout@v3
- name: 使用缓存
uses: actions/cache@master
with:
cache_type: nuget
mount: |
nuget
- name: 编译后端项目
uses: actions/aspnet@6.0
with:
project_name: ${{ env.PROJECT_NAME }}
- name: 打包上传镜像
uses: actions/docker@master
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
image: ${{ env.IMAGE_NAME }}
context: publish
tags: latest,${{ gitea.ref_name }},${{ needs.release.outputs.version }}
- name: 生成环境变量文件
env:
env_file: |
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
OWNER=${{ gitea.repository_owner }}
TAG=${{ needs.release.outputs.version }}
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
REPLICAS=${{ env.PUBLISH_REPLICAS }}
run: |
echo "$env_file">.env
- name: 复制发布脚本
uses: docker://appleboy/drone-scp
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
target: ${{ env.PUBLISH_PATH }}
source: docker-swarm.yaml,.env
- name: 部署到服务器
uses: docker://appleboy/drone-ssh
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
script: |
if docker service ls | grep -q marking-admin-api; then
docker service rm marking-admin-api
fi
cd ${{ env.PUBLISH_PATH }}
[ -f .env ] && export $(sed '/^#/d' .env)
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
- name: 发送构建通知
if: ${{ always() }}
uses: actions/webhook@master
with:
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
content_type: application/json
template: |
{
"msgtype": "markdown",
"markdown": {
"title":"项目部署通知",
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
>**构建结果**: ${{ job.status }}
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
>**代码分支**: ${{ gitea.ref_name }}
>**发布版本**: ${{ needs.release.outputs.version }}
>**提交标识**: ${{ gitea.sha }}
>**提交发起**: ${{ gitea.actor }}
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
"
}
}

View File

@ -0,0 +1,107 @@
name: 部署测试环境
on:
push:
branches:
- staging
env:
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
PROJECT_NAME: src/Marking.Admin.Entry
PUBLISH_PATH: marking.admin.api
PUBLISH_HOST: 10.255.255.3
PUBLISH_PORT: 22
PUBLISH_REPLICAS: 3 #启动副本数量
ASPNETCORE_ENVIRONMENT: Staging
jobs:
job1:
name: 编译发布
runs-on: linux-amd
steps:
- name: 下载源码
uses: actions/checkout@v3
- name: 使用缓存
uses: actions/cache@master
with:
cache_type: nuget
mount: |
nuget
- name: 编译后端项目
uses: actions/aspnet@6.0
with:
project_name: ${{ env.PROJECT_NAME }}
- name: 打包上传镜像
uses: actions/docker@master
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
image: ${{ env.IMAGE_NAME }}
context: publish
tags: latest,${{ gitea.ref_name }}
- name: 生成环境变量文件
env:
env_file: |
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
OWNER=${{ gitea.repository_owner }}
TAG=${{ gitea.ref_name }}
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
REPLICAS=${{ env.PUBLISH_REPLICAS }}
run: |
echo "$env_file">.env
- name: 复制发布脚本
uses: docker://appleboy/drone-scp
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
target: ${{ env.PUBLISH_PATH }}
source: docker-swarm.yaml,.env
- name: 部署到服务器
uses: docker://appleboy/drone-ssh
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
script: |
if docker service ls | grep -q marking-admin-api; then
docker service rm marking-admin-api
fi
cd ${{ env.PUBLISH_PATH }}
[ -f .env ] && export $(sed '/^#/d' .env)
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
- name: 发送构建通知
if: ${{ always() }}
uses: actions/webhook@master
with:
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
content_type: application/json
template: |
{
"msgtype": "markdown",
"markdown": {
"title":"项目部署通知",
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
>**构建结果**: ${{ job.status }}
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
>**代码分支**: ${{ gitea.ref_name }}
>**提交标识**: ${{ gitea.sha }}
>**提交发起**: ${{ gitea.actor }}
>**提交信息**: ${{ gitea.event.head_commit.message }}\n
"
}
}

View File

@ -0,0 +1,107 @@
name: 部署生产环境
on:
release:
types:
- published
env:
IMAGE_NAME: ${{ gitea.repository_owner }}/marking.admin.api
PROJECT_NAME: src/Marking.Admin.Entry
PUBLISH_PATH: marking.admin.api
PUBLISH_HOST: 10.255.255.146,10.255.255.74
PUBLISH_PORT: 10022
PUBLISH_REPLICAS: 3 #启动副本数量
ASPNETCORE_ENVIRONMENT: Production
jobs:
job1:
name: 编译发布
runs-on: linux-amd
steps:
- name: 下载源码
uses: actions/checkout@v3
- name: 使用缓存
uses: actions/cache@master
with:
cache_type: nuget
mount: |
nuget
- name: 编译后端项目
uses: actions/aspnet@6.0
with:
project_name: ${{ env.PROJECT_NAME }}
- name: 打包上传镜像
uses: actions/docker@master
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
image: ${{ env.IMAGE_NAME }}
context: publish
tags: latest,${{ gitea.ref_name }}
- name: 生成环境变量文件
env:
env_file: |
REGISTRY=${{ secrets.DOCKER_REGISTRY }}
OWNER=${{ gitea.repository_owner }}
TAG=${{ gitea.ref_name }}
ASPNETCORE_ENVIRONMENT=${{ env.ASPNETCORE_ENVIRONMENT }}
REPLICAS=${{ env.PUBLISH_REPLICAS }}
run: |
echo "$env_file">.env
- name: 复制发布脚本
uses: docker://appleboy/drone-scp
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
target: ${{ env.PUBLISH_PATH }}
source: docker-swarm.yaml,.env
- name: 部署到服务器
uses: docker://appleboy/drone-ssh
with:
host: ${{ env.PUBLISH_HOST }}
port: ${{ env.PUBLISH_PORT }}
username: ${{ secrets.PUBLISH_USER_NAME }}
password: ${{ secrets.PUBLISH_PASSWORD }}
script: |
if docker service ls | grep -q marking-admin-api; then
docker service rm marking-admin-api
fi
cd ${{ env.PUBLISH_PATH }}
[ -f .env ] && export $(sed '/^#/d' .env)
docker stack deploy -c docker-swarm.yaml --with-registry-auth mk
- name: 发送构建通知
if: ${{ always() }}
uses: actions/webhook@master
with:
urls: https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781
content_type: application/json
template: |
{
"msgtype": "markdown",
"markdown": {
"title":"项目部署通知",
"text": "${{ job.status == 'success' && '✅' || '❌' }}**${{ gitea.repository }}**\n
>**构建结果**: ${{ job.status }}
>**构建详情**: [点击查看](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }})
>**代码分支**: ${{ gitea.ref_name }}
>**提交标识**: ${{ gitea.sha }}
>**提交发起**: ${{ gitea.actor }}
>**提交信息**: ${{ gitea.event.release.target_commitish }}\n
"
}
}

View File

@ -0,0 +1,47 @@
using Marking.OCR.Service.Helper;
using System.Timers;
namespace Marking.OCR.Service.BackgroundServices
{
public class CheckAndDeleteFilesService : BackgroundService
{
private static System.Timers.Timer timer;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Console.Out.WriteLineAsync("定时删除jpg文件已开启" + App.HostEnvironment.EnvironmentName);
timer = new System.Timers.Timer(24 * 60 * 60 * 1000); // 设置定时器为24小时
timer.Elapsed += new ElapsedEventHandler(CheckAndDeleteFiles);
timer.Start();
await Task.CompletedTask;
}
private static void CheckAndDeleteFiles(object source, ElapsedEventArgs e)
{
Console.WriteLine("开始执行删除文件,当前时间:" + DateTime.Now);
if (!Directory.Exists(ImageHelper.FilePath))
{
Directory.CreateDirectory(ImageHelper.FilePath);
}
string folderPath = ImageHelper.FilePath;
string[] files = Directory.GetFiles(folderPath, "*.jpg");
Console.WriteLine("图片总数:" + files.Length);
foreach (string file in files)
{
DateTime creationTime = File.GetCreationTime(file);
TimeSpan timeSpan = DateTime.Now - creationTime;
if (timeSpan.TotalDays > 1) // 超过一天直接删除,避免占用磁盘空间
{
File.Delete(file);
}
}
}
}
}

View File

@ -0,0 +1,72 @@
using Marking.OCR.Service.DTO;
using Marking.OCR.Service.Helper;
using Microsoft.AspNetCore.Mvc;
using OpenCvSharp;
namespace Marking.OCR.Service.Controllers
{
[ApiController]
[Route("draw")]
public class DrawTemplateController : ControllerBase
{
private readonly ILogger<DrawTemplateController> _logger;
private readonly ImageHelper _imageHelper;
public DrawTemplateController(ILogger<DrawTemplateController> logger,
ImageHelper imageHelper)
{
_logger = logger;
this._imageHelper = imageHelper;
}
/// <summary>
/// 获取模板截图定位点坐标信息
/// </summary>
/// <returns></returns>
[HttpGet("position")]
public async Task<LocationPointViewDto> GetPositionAsync([FromQuery] LocationPointQueryDto position)
{
using var src = await _imageHelper.DownloadImageAsync(position.ImageUrl);
if (src == null)
{
throw Oops.Oh("图片加载失败!");
}
// 调整图片大小
Cv2.Resize(src, src, new Size(position.ImageWidth, position.ImageHeight));
//_imageHelper.Show(src);
// 裁剪图片
using var img_roi = new Mat(src, new Rect(position.X, position.Y, position.Width, position.Height));
//_imageHelper.Show(img_roi);
// 转换灰度图片
Cv2.CvtColor(img_roi, img_roi, ColorConversionCodes.BGR2GRAY);
//_imageHelper.Show(img_roi);
using var imgHandle = _imageHelper.ImagePreprocessing(img_roi);
var locationPoints = _imageHelper.FindLocationPoint(imgHandle, false);
if (!locationPoints.Any())
{
throw Oops.Oh("框选范围未找到定位点,请重新框选!");
}
if (locationPoints.Count() > 1)
{
throw Oops.Oh("框选范围识别到多个定位点,请重新框选!");
}
var locationPoint = locationPoints.FirstOrDefault();
return new LocationPointViewDto
{
X = locationPoint.X + position.X,
Y = locationPoint.Y + position.Y,
Width = locationPoint.Width,
Height = locationPoint.Height
};
}
}
}

View File

@ -1,40 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Marking.OCR.Service.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
}
}

View File

@ -0,0 +1,18 @@
namespace Marking.OCR.Service.DTO
{
public class LocationPointQueryDto
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string ImageUrl { get; set; }
public int ImageWidth { get; set; }
public int ImageHeight { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace Marking.OCR.Service.DTO
{
public class LocationPointViewDto
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
}

View File

@ -0,0 +1,13 @@
#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 dotnet/aspnet:8.0
WORKDIR /app
EXPOSE 80
COPY . .
ENV TZ=Asia/Shanghai
ENTRYPOINT ["dotnet", "Marking.OCR.Service.dll"]

View File

@ -0,0 +1,154 @@
using OpenCvSharp;
using OpenCvSharp.Internal.Vectors;
using Qwit;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Marking.OCR.Service.Helper
{
public class ImageHelper : Qwit.IScopedDependency
{
private readonly IHttpClientFactory _httpClientFactory;
/// <summary>
/// 图片保存文件的文件夹地址
/// </summary>
public static string FilePath => Path.Combine(Directory.GetCurrentDirectory(), "images");
public ImageHelper(IHttpClientFactory httpClientFactory)
{
this._httpClientFactory = httpClientFactory;
}
/// <summary>
/// 下载图片,缓存本地一天
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task<Mat?> DownloadImageAsync(string url)
{
//判断文件夹是否存在
if (!Directory.Exists(FilePath))
{
Directory.CreateDirectory(FilePath);
}
//文件名
var filename = $@"{url.GetMd5String()}.jpg";
//保存地址+文件名
var savePath = Path.Combine(FilePath, filename);
if (File.Exists(savePath))
{
// 文件已存在
return Cv2.ImRead(savePath);
}
// 文件不存在,需下载
var finalUrl = (url.StartsWith("http:") || url.StartsWith("https:")) ? url : $@"http:{url}";
// 下载图片
using var httpclient = _httpClientFactory.CreateClient();
var response = await httpclient.GetAsync(finalUrl);
if (response == null || !response.IsSuccessStatusCode)
{
return null;
}
var imageBytes = await response.Content.ReadAsByteArrayAsync();
// 将字节数组保存为文件
await System.IO.File.WriteAllBytesAsync(savePath, imageBytes);
// 文件已存在
return Cv2.ImRead(savePath);
}
public void Show(Mat mat, string title = "")
{
#if !DEBUG
return;
#endif
Cv2.ImShow(string.IsNullOrWhiteSpace(title) ? DateTime.UtcNow.ToString() : title, mat);
Cv2.WaitKey(0);
}
/// <summary>
/// 图像预处理
/// </summary>
public Mat ImagePreprocessing(Mat mat, double threshValue = 210)
{
// 中值滤波
Cv2.MedianBlur(mat, mat, 5);
//Show(mat, "MedianBlur");
// 高斯滤波
Cv2.GaussianBlur(mat, mat, new Size(3, 3), 0);
//Show(mat, "GaussianBlur");
// 二值化
Cv2.Threshold(mat, mat, threshValue, 255, ThresholdTypes.BinaryInv);
//Show(mat, "Threshold");
// 侵蚀
Cv2.Erode(mat, mat, Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)));
//Show(mat, "Erode");
// 膨胀
Cv2.Dilate(mat, mat, Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)));
//Show(mat, "Dilate");
return mat;
}
/// <summary>
/// 查找图片定位点
/// </summary>
/// <param name="mat"></param>
/// <returns></returns>
public IEnumerable<Rect> FindLocationPoint(Mat mat, bool showOutline = false)
{
List<Rect> rects = new List<Rect>();
// 寻找图片轮廓
Cv2.FindContours(mat, out Point[][] contours, out HierarchyIndex[] index, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
foreach (var contour in contours)
{
if (showOutline)
Show(DrawContours(mat, contour));
//外接矩形
var rect = Cv2.BoundingRect(contour);
// 计算图像内非零像素个数
using Mat roi = new Mat(mat, rect);
int nonZeroPixels = Cv2.CountNonZero(roi);
// 计算连通轮廓的面积
var area = Cv2.ContourArea(contour);
// 计算逼近轮廓
var approxContour = Cv2.ApproxPolyDP(contour, Cv2.ArcLength(contour, true) * 0.05, true);
if (Cv2.IsContourConvex(approxContour)
&& rect.Width > 10 && rect.Width < 80
&& rect.Height > 10 && rect.Height < 80
&& area > 200 && area < 3000
&& nonZeroPixels > 200)
{
rects.Add(rect);
}
}
return rects;
}
public Mat DrawContours(Mat mat, Point[] contour)
{
//转换颜色空间
Mat mat_color = new Mat();
Cv2.CvtColor(mat, mat_color, ColorConversionCodes.GRAY2BGR);
Cv2.DrawContours(mat_color, new Point[][] { contour }, -1, Scalar.Red, 2);
return mat_color;
}
}
}

View File

@ -7,6 +7,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Marking.WebExtensions" Version="1.2.1.4" />
<PackageReference Include="OpenCvSharp4" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4_.runtime.ubuntu.20.04-x64" Version="4.9.0.20240103" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using Qwit;
namespace Marking.OCR.Service.Packs
{
[DependsByPack(typeof(MarkingPack))]
internal class AppPack : QwitPack
{
public override void ConfigureServices(IServiceCollection services)
{
}
}
}

View File

@ -1,14 +1,29 @@
using Marking;
using Marking.OCR.Service.BackgroundServices;
using Qwit;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddQwitPack();
builder.Services.AddControllers(); builder.Services.AddControllers(options =>
{
// 全局异常捕获,无需在代码中写 try catch
options.Filters.Add<ExceptionFilter>();
// 全局模型赋值默认值 和 统一返回格式处理
options.Filters.Add<ModelActionFilter>();
// 全局异地登陆检验
//options.Filters.Add<AuthorizationActionFilter>();
//全局日志追踪过滤器
options.Filters.Add<TraceFilterAttribute>();
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
builder.Services.AddHostedService<CheckAndDeleteFilesService>();
var app = builder.Build(); var app = builder.Build();
app.UseQwitPack();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {

View File

@ -6,5 +6,17 @@
"ServerNodes": "http://config.23544.com:15000/,http://config.23544.com:15001/", //使, "ServerNodes": "http://config.23544.com:15000/,http://config.23544.com:15001/", //使,
"Tag": "marking", "Tag": "marking",
"Name": "阅卷后台管理" "Name": "阅卷后台管理"
},
"QwitLogServer": {
"ServerUrl": "https://log.w.23544.com:8843",
"PushKey": "XTPsAhViiJ7rR7/bGM5vH756rD+Uejy8tiuWK/7qEAWRsVj0JqLWm6rpvDWgT322",
"CheckServer": false
},
"WebPack": {
"Services": [
"Marking.Infrastructure",
"Marking.Domain",
"Marking.WebExtensions"
]
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

14
docker-swarm.yaml Normal file
View File

@ -0,0 +1,14 @@
version: "3"
services:
admin-api:
image: ${REGISTRY:-harbor.w.23544.com:8843}/marking/marking.ocr.service:${TAG:-latest}
hostname: marking
environment:
TZ: Asia/Shanghai
ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Development} #默认为开发环境
ports:
- 6555:80
deploy:
mode: replicated
replicas: ${REPLICAS:-1}

10
nuget.config Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="qwit" value="https://git.h.qwit.top:8843/api/packages/actions/nuget/index.json" />
<add key="git" value="https://gitea.23544.com/api/packages/actions/nuget/index.json"/>
<add key="marking" value="https://gitea.23544.com/api/packages/marking/nuget/index.json"/>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>