init
This commit is contained in:
parent
b5a5ffeaa3
commit
2e2ab7edd1
|
|
@ -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
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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"]
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
|
@ -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}
|
||||||
|
|
@ -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>
|
||||||
Loading…
Reference in New Issue