1
This commit is contained in:
commit
21f044712c
30
.claude/settings.local.json
Normal file
30
.claude/settings.local.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(dotnet build:*)",
|
||||
"Bash(find:*)",
|
||||
"Bash(grep:*)",
|
||||
"mcp__ide__getDiagnostics",
|
||||
"Bash(rm:*)",
|
||||
"Bash(dir:*)",
|
||||
"Bash(powershell:*)",
|
||||
"Bash(git rm:*)",
|
||||
"Bash(cmd /c \"del nul\")",
|
||||
"Bash(cmd:*)",
|
||||
"Bash(git clean:*)",
|
||||
"Bash(dotnet test:*)",
|
||||
"Bash(timeout 30 dotnet test NPP.SmartSchedue.Tests --filter \"EquipmentMaintenanceIntegrationTest\" --logger \"console;verbosity=minimal\")",
|
||||
"Bash(timeout 30 dotnet test NPP.SmartSchedue.Tests --filter \"FullyQualifiedName~EquipmentCalibrationIntegrationTest\")",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git push:*)",
|
||||
"Bash(cp:*)",
|
||||
"Bash(mv:*)",
|
||||
"Bash(dotnet run:*)",
|
||||
"Bash(mkdir:*)",
|
||||
"Bash(git restore:*)",
|
||||
"Bash(ls:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
}
|
7
.cursor/rules/sse.mdc
Normal file
7
.cursor/rules/sse.mdc
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
description: 自动排班
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
|
25
.dockerignore
Normal file
25
.dockerignore
Normal file
@ -0,0 +1,25 @@
|
||||
**/.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
|
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
403
.gitignore
vendored
Normal file
403
.gitignore
vendored
Normal file
@ -0,0 +1,403 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
|
||||
**/wwwroot/upload
|
||||
|
||||
**/NPP.SmartSchedue.Api/NPP.SmartSchedue.Api.xml
|
||||
**/NPP.SmartSchedue.Api.Contracts/NPP.SmartSchedue.Api.Contracts.xml
|
1
.idea/.idea.NPP.SmartSchedue/.idea/.name
generated
Normal file
1
.idea/.idea.NPP.SmartSchedue/.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
NPP.SmartSchedue
|
8
.idea/.idea.NPP.SmartSchedue/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.NPP.SmartSchedue/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
8
.idea/.idea.NPP.SmartSchedue/.idea/projectSettingsUpdater.xml
generated
Normal file
8
.idea/.idea.NPP.SmartSchedue/.idea/projectSettingsUpdater.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="singleClickDiffPreview" value="1" />
|
||||
<option name="unhandledExceptionsIgnoreList" value="1" />
|
||||
<option name="vcsConfiguration" value="3" />
|
||||
</component>
|
||||
</project>
|
6
.idea/.idea.NPP.SmartSchedue/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.NPP.SmartSchedue/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
234
.idea/.idea.NPP.SmartSchedue/.idea/workspace.xml
generated
Normal file
234
.idea/.idea.NPP.SmartSchedue/.idea/workspace.xml
generated
Normal file
@ -0,0 +1,234 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoGeneratedRunConfigurationManager">
|
||||
<projectFile kind="Docker">NPP.SmartSchedue.Host/NPP.SmartSchedue.Host.csproj</projectFile>
|
||||
<projectFile profileName="IIS Express">NPP.SmartSchedue.Host/NPP.SmartSchedue.Host.csproj</projectFile>
|
||||
<projectFile profileName="NPP.SmartSchedue.Host">NPP.SmartSchedue.Host/NPP.SmartSchedue.Host.csproj</projectFile>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="635f35ee-190e-4c9a-82f7-ee1c8f1bea95" name="更改" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.NPP.SmartSchedue/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.NPP.SmartSchedue/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ExecutiveSummary.md" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GeneticAlgorithmPerformanceAnalysis.md" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GeneticAlgorithmTestPlan.md" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/NPP.SmartSchedue.Api/NPP.SmartSchedue.Api.xml" beforeDir="false" afterPath="$PROJECT_DIR$/NPP.SmartSchedue.Api/NPP.SmartSchedue.Api.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/PerformanceOptimizationRecommendations.md" beforeDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="DpaMonitoringSettings">
|
||||
<option name="firstShow" value="false" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$/../../.." value="dev_schedule_2" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/../../.." />
|
||||
</component>
|
||||
<component name="GitLabMergeRequestFiltersHistory">{
|
||||
"lastFilter": {
|
||||
"state": "OPENED",
|
||||
"assignee": {
|
||||
"type": "org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestsMemberFilterValue.MergeRequestsAssigneeFilterValue",
|
||||
"username": "project_698_bot",
|
||||
"fullname": "Rider"
|
||||
}
|
||||
}
|
||||
}</component>
|
||||
<component name="GitLabMergeRequestsSettings">{
|
||||
"selectedUrlAndAccountId": {
|
||||
"first": "https://gitspace.wuxibiologics.com/npp-code-management/SPMS.Portal.git",
|
||||
"second": "46b52827-07a1-4c7c-84b0-fd07ed3ba3df"
|
||||
}
|
||||
}</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="file://$PROJECT_DIR$/NPP.SmartSchedue.Api/Services/Integration/GlobalPersonnelAllocationService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/66b2a0f1b42345cba263118414f9d183a0910/fa/1cbb630b/Enumerable.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/de363d7e26864f26a46f46b9b5e16f534c00/01/6719b288/AsyncDeterminationInterceptor.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/294078ecfce6fdb942ecfee089f09717de7a6fcfe5efd9fdb6f4f93c0fb4813/ActionMethodExecutor.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/2f657497243c260bae22d6d2c67ab907371015db851628463cc13adfaf325/Int64.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/9d3abb8c403eb01b13b989f2e737438c72cfcd9a12885edf04f7e507586ff0/BaseService.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/a4948a1287bc91a8a16e6d426a38bac34ebd47b49bf82a2772477aa9dc7908e/HostApp.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/a6eded6d58086a0199d103a8f2b10471948ce5a18b7773c815d2364b1423c68/ISelect2`16.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/c2e3bc99518b63d562a6388933d90bae1d78433cc7b77c29523941341be61a6/TransactionAsyncInterceptor.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/de533de9e7b3ea79d36aeac96b6426559cfe9f3a96b1ab66b51ce3febeda25f/TimeSpan.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/e399fc861c188bd19ebde14346e2f5f2c1a54c1c0d6fbd5cbe05227afe6d/CollectionExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="mock://diff.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
|
||||
<component name="ProblemsViewState">
|
||||
<option name="selectedTabId" value="CurrentFile" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 4
|
||||
}</component>
|
||||
<component name="ProjectId" id="30zf5rxtLF4AlMwfbHnXdMlDTzF" />
|
||||
<component name="ProjectLevelVcsManager">
|
||||
<ConfirmationsSetting value="2" id="Add" />
|
||||
</component>
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
".NET 启动设置配置文件.NPP.SmartSchedue.Host.executor": "Debug",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"ToolWindow.Debug.ShowToolbar": "false",
|
||||
"git-widget-placeholder": "dev__schedule",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "editor.preferences.fonts.default",
|
||||
"settings.editor.splitter.proportion": "0.1840796",
|
||||
"ts.external.directory.path": "C:\\GitCodeSpace\\SPMS.Portal\\zhontai.ui.admin.vue3\\node_modules\\typescript\\lib",
|
||||
"vue.rearranger.settings.migration": "true",
|
||||
"附加到进程.1596:NPP.SmartSchedue.Host.executor": "Debug",
|
||||
"附加到进程.19008:NPP.SmartSchedue.Host.executor": "Debug",
|
||||
"附加到进程.28664:NPP.SmartSchedue.Host.executor": "Debug"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager" selected=".NET 启动设置配置文件.NPP.SmartSchedue.Host">
|
||||
<configuration name="NPP.SmartSchedue.Host" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||
<option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/NPP.SmartSchedue.Host/NPP.SmartSchedue.Host.csproj" />
|
||||
<option name="LAUNCH_PROFILE_TFM" value="net9.0" />
|
||||
<option name="LAUNCH_PROFILE_NAME" value="NPP.SmartSchedue.Host" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="GENERATE_APPLICATIONHOST_CONFIG" value="1" />
|
||||
<option name="SHOW_IIS_EXPRESS_OUTPUT" value="0" />
|
||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="NPP.SmartSchedue.Host: IIS Express" type="LaunchSettings" factoryName=".NET Launch Settings Profile">
|
||||
<option name="LAUNCH_PROFILE_PROJECT_FILE_PATH" value="$PROJECT_DIR$/NPP.SmartSchedue.Host/NPP.SmartSchedue.Host.csproj" />
|
||||
<option name="LAUNCH_PROFILE_TFM" value="net9.0" />
|
||||
<option name="LAUNCH_PROFILE_NAME" value="IIS Express" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="GENERATE_APPLICATIONHOST_CONFIG" value="1" />
|
||||
<option name="SHOW_IIS_EXPRESS_OUTPUT" value="0" />
|
||||
<option name="SEND_DEBUG_REQUEST" value="1" />
|
||||
<option name="ADDITIONAL_IIS_EXPRESS_ARGUMENTS" value="" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="docker-deploy" factoryName="dockerfile" temporary="true">
|
||||
<deployment type="dockerfile">
|
||||
<settings />
|
||||
</deployment>
|
||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="NPP.SmartSchedue.Host/Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="containerName" value="npp.smartschedue.host" />
|
||||
<option name="contextFolderPath" value="C:\666 WXGitSpace\SPMS.Portal\src\modules\schedue" />
|
||||
<option name="sourceFilePath" value="NPP.SmartSchedue.Host/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="默认任务">
|
||||
<changelist id="635f35ee-190e-4c9a-82f7-ee1c8f1bea95" name="更改" comment="" />
|
||||
<created>1754635142915</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1754635142915</updated>
|
||||
<workItem from="1754635143882" duration="4343000" />
|
||||
<workItem from="1754874747747" duration="7000" />
|
||||
<workItem from="1754878274269" duration="11438000" />
|
||||
<workItem from="1755480136705" duration="6336000" />
|
||||
<workItem from="1755492788122" duration="12633000" />
|
||||
<workItem from="1755517970088" duration="5154000" />
|
||||
<workItem from="1755572773370" duration="1830000" />
|
||||
<workItem from="1755583838242" duration="13230000" />
|
||||
<workItem from="1755661227196" duration="9632000" />
|
||||
<workItem from="1755677504783" duration="2660000" />
|
||||
<workItem from="1755681064691" duration="1596000" />
|
||||
<workItem from="1755695756877" duration="3164000" />
|
||||
<workItem from="1755752854232" duration="10000" />
|
||||
<workItem from="1755752884301" duration="4360000" />
|
||||
<workItem from="1755759793828" duration="8749000" />
|
||||
<workItem from="1755825348947" duration="4502000" />
|
||||
<workItem from="1755850912137" duration="2031000" />
|
||||
<workItem from="1755852977655" duration="1188000" />
|
||||
<workItem from="1756084492195" duration="43899000" />
|
||||
<workItem from="1756185335516" duration="36937000" />
|
||||
<workItem from="1756289004055" duration="1442000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
<option name="exactExcludedFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../../../npp-smart-schedule-portal/node_modules/zrender/index.js" />
|
||||
<option value="$PROJECT_DIR$/../../../npp-smart-schedule-portal/node_modules/zrender/index.d.ts" />
|
||||
<option value="$PROJECT_DIR$/../../../zhontai.ui.admin.vue3/node_modules/zrender/index.js" />
|
||||
<option value="$PROJECT_DIR$/../../../zhontai.ui.admin.vue3/node_modules/zrender/index.d.ts" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="UnityCheckinConfiguration" checkUnsavedScenes="true" />
|
||||
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
<breakpoints>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.OperationCanceledException" breakIfHandledByOtherCode="false" displayValue="System.OperationCanceledException" />
|
||||
<option name="timeStamp" value="1" />
|
||||
</breakpoint>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.Threading.Tasks.TaskCanceledException" breakIfHandledByOtherCode="false" displayValue="System.Threading.Tasks.TaskCanceledException" />
|
||||
<option name="timeStamp" value="2" />
|
||||
</breakpoint>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" />
|
||||
<option name="timeStamp" value="3" />
|
||||
</breakpoint>
|
||||
</breakpoints>
|
||||
</breakpoint-manager>
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
</project>
|
130
CLAUDE.md
Normal file
130
CLAUDE.md
Normal file
@ -0,0 +1,130 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
### 代码开发规范
|
||||
- **引用检查**:编写代码时,必须检查所有using引用是否正确,确保引用的命名空间和类存在
|
||||
- **编译验证**:完成一个功能时必须执行编译检查,发现错误立即修复,确保代码能够正常编译
|
||||
|
||||
### 深度思考与详细实现要求
|
||||
- **深度思考原则**:对每个业务问题都要进行深度思考,分析所有可能的边界情况和业务场景
|
||||
- **最终抉择要求**:在分析各种方案后,必须给出明确的最终决策和理由,不允许含糊其辞
|
||||
- **详细实现标准**:所有功能都必须详细实现,不允许简化或省略关键逻辑
|
||||
- **完整性验证**:实现功能时必须考虑所有相关的上下文和依赖关系
|
||||
- **业务场景覆盖**:确保代码能够处理所有合理的业务场景,包括异常情况
|
||||
- **错误处理完整性**:每个方法都必须包含适当的异常处理和错误信息
|
||||
- **注释详细程度**:关键业务逻辑必须包含详细的业务思考过程注释
|
||||
|
||||
## 项目概述
|
||||
|
||||
NPP.SmartSchedue 是一个智能生产调度系统,基于 .NET 9.0 和中台Admin框架开发,实现生产任务的智能排班和调度管理。
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 项目结构
|
||||
- **NPP.SmartSchedue.Api.Contracts**: 契约层,包含实体、接口和DTO定义
|
||||
- **NPP.SmartSchedue.Api**: 业务逻辑层,包含Repository和Service实现
|
||||
- **NPP.SmartSchedue.Host**: 宿主程序,Web API启动入口
|
||||
- **NPP.SmartSchedue.Tests**: 单元测试项目
|
||||
|
||||
### 核心领域模块
|
||||
1. **Work**: 工作任务管理
|
||||
- WorkOrderEntity: 工作任务实体(支持多租户)
|
||||
- WorkOrderFLPersonnelEntity: 任务与FL人员关联
|
||||
- ProcessEntity: 工序管理
|
||||
- ProcessGroupEntity: 工序组管理
|
||||
|
||||
2. **Time**: 时间和班次管理
|
||||
- ShiftEntity: 班次定义
|
||||
- ShiftRuleEntity: 班次规则
|
||||
- CalendarEntity: 日历管理
|
||||
- EmployeeLeaveEntity: 员工请假
|
||||
|
||||
3. **Personnel**: 人员管理
|
||||
- PersonnelQualificationEntity: 人员资质
|
||||
- PersonnelWorkLimitEntity: 人员工作限制
|
||||
- QualificationEntity: 资质定义
|
||||
|
||||
4. **Schedule**: 排班调度
|
||||
- AutoScheduleInput: 自动排班输入
|
||||
- ScheduleValidationService: 排班验证服务
|
||||
- TaskIntegrationInput: 任务整合输入
|
||||
|
||||
### 技术栈
|
||||
- **.NET 9.0**: 主要开发框架
|
||||
- **FreeSql**: ORM框架,支持MySQL
|
||||
- **ZhonTai.Admin**: 中台管理框架
|
||||
- **DotNetCore.CAP**: 事件总线,支持RabbitMQ
|
||||
- **xUnit**: 单元测试框架
|
||||
|
||||
## 常用命令
|
||||
|
||||
### 构建和运行
|
||||
```bash
|
||||
# 构建整个解决方案
|
||||
dotnet build NPP.SmartSchedue.sln
|
||||
|
||||
# 运行Host项目
|
||||
dotnet run --project NPP.SmartSchedue.Host
|
||||
|
||||
# 发布项目
|
||||
dotnet publish NPP.SmartSchedue.Host -c Release
|
||||
```
|
||||
|
||||
### 测试
|
||||
```bash
|
||||
# 运行所有测试
|
||||
dotnet test NPP.SmartSchedue.Tests
|
||||
|
||||
# 运行特定测试文件
|
||||
dotnet test NPP.SmartSchedue.Tests --filter ClassName=TestName
|
||||
|
||||
# 生成测试覆盖率报告
|
||||
dotnet test NPP.SmartSchedue.Tests --collect:"XPlat Code Coverage"
|
||||
```
|
||||
|
||||
### 数据库相关
|
||||
```bash
|
||||
# 项目使用FreeSql进行数据库操作,支持Code First
|
||||
# 数据库连接配置在 ConfigCenter/dbconfig.json
|
||||
# 初始化SQL脚本位于 ConfigCenter/createdbsql.txt
|
||||
```
|
||||
|
||||
## 开发规范
|
||||
|
||||
### 实体设计
|
||||
- 工作任务相关实体继承 `EntityTenant`(支持多租户)
|
||||
- 基础配置实体继承 `EntityBase`
|
||||
- 使用 FreeSql 特性进行数据库映射
|
||||
|
||||
### 服务层架构
|
||||
- Repository层:数据访问,继承自 `AppRepositoryBase<T>`
|
||||
- Service层:业务逻辑,实现对应的Interface
|
||||
- 输入输出模型:使用Input/Output后缀命名
|
||||
|
||||
### 命名约定
|
||||
- 实体类:Entity后缀
|
||||
- 仓储接口:I前缀 + Repository后缀
|
||||
- 服务接口:I前缀 + Service后缀
|
||||
- 数据库表名:使用 DbConsts.TableNamePrefix 前缀
|
||||
|
||||
### 排班业务逻辑要点
|
||||
- 任务状态使用 `WorkOrderStatusEnum` 枚举管理
|
||||
- 支持任务优先级、紧急程度、复杂度等多维度排序
|
||||
- FL人员与任务为多对多关系,通过 WorkOrderFLPersonnelEntity 关联
|
||||
- 支持批量任务整合和验证功能
|
||||
- 班次规则支持多种类型,通过 ShiftRuleTypeEnum 管理
|
||||
|
||||
### 多任务验证架构决策
|
||||
- **单一验证原则**:所有冲突检查统一在 `ValidateWorkOrderWithBatchContextAsync` 中完成
|
||||
- **批次上下文集成**:每个单任务验证都考虑批次内其他任务的影响
|
||||
- **取消跨任务验证**:原有的 `CheckCrossTaskConflictsAsync` 已被移除,避免重复验证
|
||||
- **全面冲突检查**:包含时间冲突、工作量限制、班次规则、时间段重叠等所有验证维度
|
||||
- **性能优化**:减少重复查询,统一数据获取和验证逻辑
|
||||
|
||||
## 配置文件
|
||||
- 应用配置:ConfigCenter/appconfig.json
|
||||
- 数据库配置:ConfigCenter/dbconfig.json
|
||||
- JWT配置:ConfigCenter/jwtconfig.json
|
||||
- 缓存配置:ConfigCenter/cacheconfig.json
|
||||
- CAP事件总线:appsettings.json中的CAP节点
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 npp.smartschedue
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
22
NPP.SmartSchedue.Api.Contracts/Core/Consts/DbConsts.cs
Normal file
22
NPP.SmartSchedue.Api.Contracts/Core/Consts/DbConsts.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
/// <summary>
|
||||
/// 数据库常量
|
||||
/// </summary>
|
||||
public static partial class DbConsts
|
||||
{
|
||||
/// <summary>
|
||||
/// 表名前缀
|
||||
/// </summary>
|
||||
public const string TableNamePrefix = "sse_";
|
||||
|
||||
/// <summary>
|
||||
/// aem前缀
|
||||
/// </summary>
|
||||
public const string AEMTableNamePrefix = "aem_";
|
||||
|
||||
/// <summary>
|
||||
/// 旧表名前缀
|
||||
/// </summary>
|
||||
public const string TableOldNamePrefix = "";
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
/// <summary>
|
||||
/// 订阅命名
|
||||
/// </summary>
|
||||
public class SubscribeNames
|
||||
{
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备状态枚举
|
||||
/// </summary>
|
||||
public enum EquipmentStatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 可用
|
||||
/// </summary>
|
||||
Available = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 使用中
|
||||
/// </summary>
|
||||
InUse = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 维护中
|
||||
/// </summary>
|
||||
Maintenance = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 故障
|
||||
/// </summary>
|
||||
Fault = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 停用
|
||||
/// </summary>
|
||||
Disabled = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 维护状态枚举
|
||||
/// </summary>
|
||||
public enum MaintenanceStatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 已计划
|
||||
/// </summary>
|
||||
Scheduled = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
InProgress = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
Completed = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 已取消
|
||||
/// </summary>
|
||||
Cancelled = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验状态枚举
|
||||
/// </summary>
|
||||
public enum CalibrationStatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 已计划
|
||||
/// </summary>
|
||||
Scheduled = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
InProgress = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
Completed = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 已取消
|
||||
/// </summary>
|
||||
Cancelled = 4
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 工序分类枚举
|
||||
/// </summary>
|
||||
public enum ProcessCategoryEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 准备工序
|
||||
/// </summary>
|
||||
Preparation = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 生产工序
|
||||
/// </summary>
|
||||
Production = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 质检工序
|
||||
/// </summary>
|
||||
QualityControl = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 包装工序
|
||||
/// </summary>
|
||||
Packaging = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 维护工序
|
||||
/// </summary>
|
||||
Maintenance = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 清洁工序
|
||||
/// </summary>
|
||||
Cleaning = 6
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 资质等级枚举
|
||||
/// 业务思考:定义资质的技能等级,支持技能匹配和人员成长路径管理
|
||||
/// </summary>
|
||||
public enum QualificationLevelEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 初级 - 基础技能水平
|
||||
/// 业务场景:新员工、实习生等入门级别
|
||||
/// </summary>
|
||||
Junior = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 中级 - 熟练技能水平
|
||||
/// 业务场景:有一定工作经验的员工
|
||||
/// </summary>
|
||||
Intermediate = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 高级 - 专业技能水平
|
||||
/// 业务场景:资深员工、技术专家
|
||||
/// </summary>
|
||||
Senior = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 专家级 - 顶级技能水平
|
||||
/// 业务场景:技术带头人、首席技师
|
||||
/// </summary>
|
||||
Expert = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 不限等级 - 对技能等级无要求
|
||||
/// 业务场景:基础操作、通用技能
|
||||
/// </summary>
|
||||
Any = 0
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 资质要求类型枚举
|
||||
/// 业务思考:定义工序对资质的不同要求级别,支持灵活的人员匹配策略
|
||||
/// </summary>
|
||||
public enum QualificationRequirementTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需资质 - 必须拥有此资质才能执行工序
|
||||
/// 业务场景:安全操作证、特种设备操作证等强制性资质
|
||||
/// </summary>
|
||||
Required = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 优选资质 - 拥有此资质的人员优先分配
|
||||
/// 业务场景:高级技能证书、专业认证等加分项资质
|
||||
/// </summary>
|
||||
Preferred = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 可选资质 - 拥有此资质可以提高工作效率
|
||||
/// 业务场景:辅助技能、相关经验认证等
|
||||
/// </summary>
|
||||
Optional = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 禁止资质 - 拥有此资质的人员不能执行该工序
|
||||
/// 业务场景:某些冲突的资质限制,如化学品处理与食品加工
|
||||
/// </summary>
|
||||
Forbidden = 4
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则类型枚举
|
||||
/// </summary>
|
||||
public enum ShiftRuleTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 优先指定人员班次
|
||||
/// </summary>
|
||||
PrioritizeSpecifiedPersonnel = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 按班次分组计算总任务数
|
||||
/// </summary>
|
||||
CalculateTasksByShiftGroup = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 个人周最大任务数限制
|
||||
/// </summary>
|
||||
IndividualWeeklyTaskLimit = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 班次连续性限制
|
||||
/// </summary>
|
||||
ShiftContinuityRestriction = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 周末连续工作限制
|
||||
/// </summary>
|
||||
WeekendConsecutiveRestriction = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 连续工作天数限制
|
||||
/// </summary>
|
||||
ConsecutiveWorkDaysLimit = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 班次后强制休息
|
||||
/// </summary>
|
||||
MandatoryRestAfterShift = 7,
|
||||
|
||||
/// <summary>
|
||||
/// 年度班次平均分配
|
||||
/// </summary>
|
||||
YearlyShiftAverageDistribution = 8,
|
||||
|
||||
/// <summary>
|
||||
/// 人员资质匹配
|
||||
/// </summary>
|
||||
PersonnelQualificationMatch = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 设备可用性检查
|
||||
/// </summary>
|
||||
EquipmentAvailabilityCheck = 10
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态枚举
|
||||
/// </summary>
|
||||
public enum WorkOrderStatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 待提交
|
||||
/// </summary>
|
||||
PendingSubmit = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 待复核
|
||||
/// </summary>
|
||||
PendingReview = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 待整合
|
||||
/// </summary>
|
||||
PendingIntegration = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 待分配
|
||||
/// </summary>
|
||||
PendingAssignment = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 已分配
|
||||
/// </summary>
|
||||
Assigned = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
InProgress = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
Completed = 7
|
||||
}
|
632
NPP.SmartSchedue.Api.Contracts/Domain/Common/DateRange.cs
Normal file
632
NPP.SmartSchedue.Api.Contracts/Domain/Common/DateRange.cs
Normal file
@ -0,0 +1,632 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// 日期范围类
|
||||
/// 智能排班系统中的时间区间管理,支持工作日计算、工时统计和时间跨度分析
|
||||
/// 深度业务思考:提供完整的时间范围操作,支持复杂的排班业务场景
|
||||
/// </summary>
|
||||
public class DateRange
|
||||
{
|
||||
#region 属性定义
|
||||
|
||||
/// <summary>
|
||||
/// 开始日期
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束日期
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间跨度
|
||||
/// 计算开始日期和结束日期之间的时间差
|
||||
/// </summary>
|
||||
public TimeSpan Duration => EndDate.Date - StartDate.Date;
|
||||
|
||||
/// <summary>
|
||||
/// 总天数(包含开始和结束日期)
|
||||
/// </summary>
|
||||
public int TotalDays => Duration.Days + 1;
|
||||
|
||||
/// <summary>
|
||||
/// 纯粹的天数差(不包含结束日期)
|
||||
/// </summary>
|
||||
public int DurationDays => Duration.Days;
|
||||
|
||||
/// <summary>
|
||||
/// 工作日天数
|
||||
/// 排除周末和节假日的实际工作天数
|
||||
/// </summary>
|
||||
public int WorkingDays => CalculateWorkingDays();
|
||||
|
||||
/// <summary>
|
||||
/// 自然工作日天数
|
||||
/// 仅排除周末,不考虑节假日
|
||||
/// </summary>
|
||||
public int NaturalWorkingDays => CalculateNaturalWorkingDays();
|
||||
|
||||
/// <summary>
|
||||
/// 周末天数
|
||||
/// </summary>
|
||||
public int WeekendDays => CalculateWeekendDays();
|
||||
|
||||
/// <summary>
|
||||
/// 节假日天数
|
||||
/// </summary>
|
||||
public int HolidayDays => CalculateHolidayDays();
|
||||
|
||||
/// <summary>
|
||||
/// 是否为有效的日期范围
|
||||
/// </summary>
|
||||
public bool IsValid => StartDate <= EndDate;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为单日范围
|
||||
/// </summary>
|
||||
public bool IsSingleDay => StartDate.Date == EndDate.Date;
|
||||
|
||||
/// <summary>
|
||||
/// 是否跨越多个月份
|
||||
/// </summary>
|
||||
public bool SpansMultipleMonths => StartDate.Month != EndDate.Month || StartDate.Year != EndDate.Year;
|
||||
|
||||
/// <summary>
|
||||
/// 是否跨越多个年份
|
||||
/// </summary>
|
||||
public bool SpansMultipleYears => StartDate.Year != EndDate.Year;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
/// <summary>
|
||||
/// 默认构造函数
|
||||
/// </summary>
|
||||
public DateRange()
|
||||
{
|
||||
StartDate = DateTime.Today;
|
||||
EndDate = DateTime.Today;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定开始和结束日期的构造函数
|
||||
/// </summary>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
public DateRange(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
StartDate = startDate.Date;
|
||||
EndDate = endDate.Date;
|
||||
|
||||
if (!IsValid)
|
||||
{
|
||||
throw new ArgumentException("结束日期不能早于开始日期");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定日期开始,持续指定天数的构造函数
|
||||
/// </summary>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="days">持续天数</param>
|
||||
public DateRange(DateTime startDate, int days)
|
||||
{
|
||||
if (days < 0)
|
||||
{
|
||||
throw new ArgumentException("天数不能为负数");
|
||||
}
|
||||
|
||||
StartDate = startDate.Date;
|
||||
EndDate = startDate.Date.AddDays(days - 1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 工时计算方法
|
||||
|
||||
/// <summary>
|
||||
/// 计算标准工时
|
||||
/// 基于每天8小时的标准工作时间
|
||||
/// </summary>
|
||||
/// <param name="dailyStandardHours">每日标准工时,默认8小时</param>
|
||||
/// <returns>总标准工时</returns>
|
||||
public decimal CalculateStandardHours(decimal dailyStandardHours = 8.0m)
|
||||
{
|
||||
return WorkingDays * dailyStandardHours;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算自然日标准工时
|
||||
/// 基于总天数计算,不考虑工作日
|
||||
/// </summary>
|
||||
/// <param name="dailyStandardHours">每日标准工时,默认8小时</param>
|
||||
/// <returns>总标准工时</returns>
|
||||
public decimal CalculateNaturalStandardHours(decimal dailyStandardHours = 8.0m)
|
||||
{
|
||||
return TotalDays * dailyStandardHours;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算工作日工时
|
||||
/// 仅计算工作日的工时,排除周末和节假日
|
||||
/// </summary>
|
||||
/// <param name="dailyWorkingHours">每个工作日的工时,默认8小时</param>
|
||||
/// <returns>工作日总工时</returns>
|
||||
public decimal CalculateWorkingHours(decimal dailyWorkingHours = 8.0m)
|
||||
{
|
||||
return WorkingDays * dailyWorkingHours;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算可用工时
|
||||
/// 考虑具体的工作时间配置
|
||||
/// </summary>
|
||||
/// <param name="workingTimeConfig">工作时间配置</param>
|
||||
/// <returns>可用总工时</returns>
|
||||
public decimal CalculateAvailableHours(WorkingTimeConfiguration workingTimeConfig = null)
|
||||
{
|
||||
if (workingTimeConfig == null)
|
||||
{
|
||||
return CalculateWorkingHours();
|
||||
}
|
||||
|
||||
decimal totalHours = 0;
|
||||
var currentDate = StartDate;
|
||||
|
||||
while (currentDate <= EndDate)
|
||||
{
|
||||
if (IsWorkingDay(currentDate))
|
||||
{
|
||||
totalHours += workingTimeConfig.GetDailyWorkingHours(currentDate);
|
||||
}
|
||||
currentDate = currentDate.AddDays(1);
|
||||
}
|
||||
|
||||
return totalHours;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 日期判断方法
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定日期是否在范围内
|
||||
/// </summary>
|
||||
/// <param name="date">要判断的日期</param>
|
||||
/// <returns>是否在范围内</returns>
|
||||
public bool Contains(DateTime date)
|
||||
{
|
||||
var checkDate = date.Date;
|
||||
return checkDate >= StartDate && checkDate <= EndDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否与另一个日期范围重叠
|
||||
/// </summary>
|
||||
/// <param name="other">另一个日期范围</param>
|
||||
/// <returns>是否重叠</returns>
|
||||
public bool Overlaps(DateRange other)
|
||||
{
|
||||
if (other == null) return false;
|
||||
return StartDate <= other.EndDate && EndDate >= other.StartDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否完全包含另一个日期范围
|
||||
/// </summary>
|
||||
/// <param name="other">另一个日期范围</param>
|
||||
/// <returns>是否完全包含</returns>
|
||||
public bool Contains(DateRange other)
|
||||
{
|
||||
if (other == null) return false;
|
||||
return StartDate <= other.StartDate && EndDate >= other.EndDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定日期是否为工作日
|
||||
/// </summary>
|
||||
/// <param name="date">要判断的日期</param>
|
||||
/// <returns>是否为工作日</returns>
|
||||
public bool IsWorkingDay(DateTime date)
|
||||
{
|
||||
// 排除周末
|
||||
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 排除节假日
|
||||
return !IsHoliday(date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定日期是否为节假日
|
||||
/// </summary>
|
||||
/// <param name="date">要判断的日期</param>
|
||||
/// <returns>是否为节假日</returns>
|
||||
public bool IsHoliday(DateTime date)
|
||||
{
|
||||
// 这里可以集成具体的节假日数据源
|
||||
// 暂时返回false,实际项目中需要根据具体需求实现
|
||||
return HolidayProvider.IsHoliday(date);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 范围操作方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取与另一个日期范围的交集
|
||||
/// </summary>
|
||||
/// <param name="other">另一个日期范围</param>
|
||||
/// <returns>交集范围,如果没有交集则返回null</returns>
|
||||
public DateRange Intersect(DateRange other)
|
||||
{
|
||||
if (other == null || !Overlaps(other))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var intersectStart = StartDate > other.StartDate ? StartDate : other.StartDate;
|
||||
var intersectEnd = EndDate < other.EndDate ? EndDate : other.EndDate;
|
||||
|
||||
return new DateRange(intersectStart, intersectEnd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取与另一个日期范围的并集
|
||||
/// </summary>
|
||||
/// <param name="other">另一个日期范围</param>
|
||||
/// <returns>并集范围</returns>
|
||||
public DateRange Union(DateRange other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return new DateRange(StartDate, EndDate);
|
||||
}
|
||||
|
||||
var unionStart = StartDate < other.StartDate ? StartDate : other.StartDate;
|
||||
var unionEnd = EndDate > other.EndDate ? EndDate : other.EndDate;
|
||||
|
||||
return new DateRange(unionStart, unionEnd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 扩展日期范围
|
||||
/// </summary>
|
||||
/// <param name="daysBefore">向前扩展的天数</param>
|
||||
/// <param name="daysAfter">向后扩展的天数</param>
|
||||
/// <returns>扩展后的日期范围</returns>
|
||||
public DateRange Extend(int daysBefore, int daysAfter)
|
||||
{
|
||||
return new DateRange(
|
||||
StartDate.AddDays(-daysBefore),
|
||||
EndDate.AddDays(daysAfter)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拆分日期范围为指定天数的子范围
|
||||
/// </summary>
|
||||
/// <param name="chunkSize">每个子范围的天数</param>
|
||||
/// <returns>子范围列表</returns>
|
||||
public List<DateRange> Split(int chunkSize)
|
||||
{
|
||||
if (chunkSize <= 0)
|
||||
{
|
||||
throw new ArgumentException("块大小必须大于0");
|
||||
}
|
||||
|
||||
var chunks = new List<DateRange>();
|
||||
var currentStart = StartDate;
|
||||
|
||||
while (currentStart <= EndDate)
|
||||
{
|
||||
var currentEnd = currentStart.AddDays(chunkSize - 1);
|
||||
if (currentEnd > EndDate)
|
||||
{
|
||||
currentEnd = EndDate;
|
||||
}
|
||||
|
||||
chunks.Add(new DateRange(currentStart, currentEnd));
|
||||
currentStart = currentEnd.AddDays(1);
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 日期枚举方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取范围内的所有日期
|
||||
/// </summary>
|
||||
/// <returns>日期列表</returns>
|
||||
public List<DateTime> GetAllDates()
|
||||
{
|
||||
var dates = new List<DateTime>();
|
||||
var currentDate = StartDate;
|
||||
|
||||
while (currentDate <= EndDate)
|
||||
{
|
||||
dates.Add(currentDate);
|
||||
currentDate = currentDate.AddDays(1);
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取范围内的所有工作日
|
||||
/// </summary>
|
||||
/// <returns>工作日列表</returns>
|
||||
public List<DateTime> GetWorkingDays()
|
||||
{
|
||||
return GetAllDates().Where(IsWorkingDay).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取范围内的所有周末
|
||||
/// </summary>
|
||||
/// <returns>周末日期列表</returns>
|
||||
public List<DateTime> GetWeekends()
|
||||
{
|
||||
return GetAllDates().Where(date =>
|
||||
date.DayOfWeek == DayOfWeek.Saturday ||
|
||||
date.DayOfWeek == DayOfWeek.Sunday).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取范围内的所有节假日
|
||||
/// </summary>
|
||||
/// <returns>节假日列表</returns>
|
||||
public List<DateTime> GetHolidays()
|
||||
{
|
||||
return GetAllDates().Where(IsHoliday).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有计算方法
|
||||
|
||||
/// <summary>
|
||||
/// 计算工作日天数
|
||||
/// </summary>
|
||||
private int CalculateWorkingDays()
|
||||
{
|
||||
return GetWorkingDays().Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算自然工作日天数(仅排除周末)
|
||||
/// </summary>
|
||||
private int CalculateNaturalWorkingDays()
|
||||
{
|
||||
var workDays = 0;
|
||||
var currentDate = StartDate;
|
||||
|
||||
while (currentDate <= EndDate)
|
||||
{
|
||||
if (currentDate.DayOfWeek != DayOfWeek.Saturday &&
|
||||
currentDate.DayOfWeek != DayOfWeek.Sunday)
|
||||
{
|
||||
workDays++;
|
||||
}
|
||||
currentDate = currentDate.AddDays(1);
|
||||
}
|
||||
|
||||
return workDays;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算周末天数
|
||||
/// </summary>
|
||||
private int CalculateWeekendDays()
|
||||
{
|
||||
return GetWeekends().Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算节假日天数
|
||||
/// </summary>
|
||||
private int CalculateHolidayDays()
|
||||
{
|
||||
return GetHolidays().Count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 静态工厂方法
|
||||
|
||||
/// <summary>
|
||||
/// 创建今天的日期范围
|
||||
/// </summary>
|
||||
public static DateRange Today()
|
||||
{
|
||||
return new DateRange(DateTime.Today, DateTime.Today);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建本周的日期范围
|
||||
/// </summary>
|
||||
public static DateRange ThisWeek()
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var startOfWeek = today.AddDays(-(int)today.DayOfWeek);
|
||||
var endOfWeek = startOfWeek.AddDays(6);
|
||||
return new DateRange(startOfWeek, endOfWeek);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建本月的日期范围
|
||||
/// </summary>
|
||||
public static DateRange ThisMonth()
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var startOfMonth = new DateTime(today.Year, today.Month, 1);
|
||||
var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
|
||||
return new DateRange(startOfMonth, endOfMonth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建本年的日期范围
|
||||
/// </summary>
|
||||
public static DateRange ThisYear()
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var startOfYear = new DateTime(today.Year, 1, 1);
|
||||
var endOfYear = new DateTime(today.Year, 12, 31);
|
||||
return new DateRange(startOfYear, endOfYear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建指定月份的日期范围
|
||||
/// </summary>
|
||||
public static DateRange ForMonth(int year, int month)
|
||||
{
|
||||
var startOfMonth = new DateTime(year, month, 1);
|
||||
var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
|
||||
return new DateRange(startOfMonth, endOfMonth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建指定年份的日期范围
|
||||
/// </summary>
|
||||
public static DateRange ForYear(int year)
|
||||
{
|
||||
var startOfYear = new DateTime(year, 1, 1);
|
||||
var endOfYear = new DateTime(year, 12, 31);
|
||||
return new DateRange(startOfYear, endOfYear);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 重写方法
|
||||
|
||||
/// <summary>
|
||||
/// 重写ToString方法
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
if (IsSingleDay)
|
||||
{
|
||||
return StartDate.ToString("yyyy-MM-dd");
|
||||
}
|
||||
return $"{StartDate:yyyy-MM-dd} ~ {EndDate:yyyy-MM-dd} ({TotalDays}天)";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写Equals方法
|
||||
/// </summary>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is DateRange other)
|
||||
{
|
||||
return StartDate == other.StartDate && EndDate == other.EndDate;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写GetHashCode方法
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(StartDate, EndDate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 支持类定义
|
||||
|
||||
/// <summary>
|
||||
/// 工作时间配置
|
||||
/// </summary>
|
||||
public class WorkingTimeConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// 标准每日工作时间
|
||||
/// </summary>
|
||||
public decimal StandardDailyHours { get; set; } = 8.0m;
|
||||
|
||||
/// <summary>
|
||||
/// 特殊日期工作时间配置
|
||||
/// Key: 日期, Value: 工作时间
|
||||
/// </summary>
|
||||
public Dictionary<DateTime, decimal> SpecialDayHours { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期的工作时间
|
||||
/// </summary>
|
||||
public decimal GetDailyWorkingHours(DateTime date)
|
||||
{
|
||||
return SpecialDayHours.GetValueOrDefault(date.Date, StandardDailyHours);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节假日提供者
|
||||
/// </summary>
|
||||
public static class HolidayProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 节假日缓存
|
||||
/// </summary>
|
||||
private static readonly HashSet<DateTime> _holidays = new();
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否为节假日
|
||||
/// </summary>
|
||||
public static bool IsHoliday(DateTime date)
|
||||
{
|
||||
// 这里可以集成具体的节假日数据源
|
||||
// 例如:国家法定节假日API、企业自定义节假日等
|
||||
return _holidays.Contains(date.Date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加节假日
|
||||
/// </summary>
|
||||
public static void AddHoliday(DateTime date)
|
||||
{
|
||||
_holidays.Add(date.Date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量添加节假日
|
||||
/// </summary>
|
||||
public static void AddHolidays(IEnumerable<DateTime> dates)
|
||||
{
|
||||
foreach (var date in dates)
|
||||
{
|
||||
_holidays.Add(date.Date);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节假日
|
||||
/// </summary>
|
||||
public static void RemoveHoliday(DateTime date)
|
||||
{
|
||||
_holidays.Remove(date.Date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有节假日
|
||||
/// </summary>
|
||||
public static void ClearHolidays()
|
||||
{
|
||||
_holidays.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备校验实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.AEMTableNamePrefix + "equipment_calibration")]
|
||||
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(EquipmentId) + "," + nameof(CalibrationDate))]
|
||||
[Index("idx_{tablename}_02", nameof(TenantId) + "," + nameof(CalibrationType))]
|
||||
[Index("idx_{tablename}_03", nameof(TenantId) + "," + nameof(Status))]
|
||||
public partial class EquipmentCalibrationEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long EquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string EquipmentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string CalibrationType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验日期
|
||||
/// </summary>
|
||||
public DateTime CalibrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验开始时间
|
||||
/// </summary>
|
||||
public DateTime? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验结束时间
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验时长(小时)
|
||||
/// </summary>
|
||||
public decimal? CalibrationHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验人员ID
|
||||
/// </summary>
|
||||
public long? CalibrationPersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验人员姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string CalibrationPersonName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验机构
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string CalibrationInstitution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验证书编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string CertificateNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验结果
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string CalibrationResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验精度
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string CalibrationAccuracy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验费用
|
||||
/// </summary>
|
||||
public decimal? CalibrationCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(0-计划中,1-进行中,2-已完成,3-已取消)
|
||||
/// </summary>
|
||||
public int Status { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否计划校验
|
||||
/// </summary>
|
||||
public bool IsPlanned { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 计划校验周期(天)
|
||||
/// </summary>
|
||||
public int? PlannedCycle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次计划校验日期
|
||||
/// </summary>
|
||||
public DateTime? NextPlannedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验标准
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string CalibrationStandard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验方法
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string CalibrationMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验环境要求
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string EnvironmentalRequirements { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验报告路径
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string ReportPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验类型枚举
|
||||
/// </summary>
|
||||
public static class CalibrationType
|
||||
{
|
||||
/// <summary>
|
||||
/// 定期校验
|
||||
/// </summary>
|
||||
public const string Regular = "Regular";
|
||||
|
||||
/// <summary>
|
||||
/// 首次校验
|
||||
/// </summary>
|
||||
public const string Initial = "Initial";
|
||||
|
||||
/// <summary>
|
||||
/// 重新校验
|
||||
/// </summary>
|
||||
public const string Recalibration = "Recalibration";
|
||||
|
||||
/// <summary>
|
||||
/// 临时校验
|
||||
/// </summary>
|
||||
public const string Temporary = "Temporary";
|
||||
|
||||
/// <summary>
|
||||
/// 强制校验
|
||||
/// </summary>
|
||||
public const string Mandatory = "Mandatory";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验结果枚举
|
||||
/// </summary>
|
||||
public static class CalibrationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 合格
|
||||
/// </summary>
|
||||
public const string Pass = "Pass";
|
||||
|
||||
/// <summary>
|
||||
/// 不合格
|
||||
/// </summary>
|
||||
public const string Fail = "Fail";
|
||||
|
||||
/// <summary>
|
||||
/// 部分合格
|
||||
/// </summary>
|
||||
public const string Partial = "Partial";
|
||||
|
||||
/// <summary>
|
||||
/// 待定
|
||||
/// </summary>
|
||||
public const string Pending = "Pending";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验状态枚举
|
||||
/// </summary>
|
||||
public static class CalibrationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 计划中
|
||||
/// </summary>
|
||||
public const int Planned = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
public const int InProgress = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
public const int Completed = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 已取消
|
||||
/// </summary>
|
||||
public const int Cancelled = 3;
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备基本信息实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.AEMTableNamePrefix + "equipment")]
|
||||
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(InternalNumber), true)]
|
||||
[Index("idx_{tablename}_02", nameof(TenantId) + "," + nameof(EquipmentType))]
|
||||
[Index("idx_{tablename}_03", nameof(TenantId) + "," + nameof(Status))]
|
||||
public partial class EquipmentEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备型号
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string InternalNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 房间号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string RoomNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string EquipmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态(0-正常,1-维护,2-校验,3-故障,4-报废)
|
||||
/// </summary>
|
||||
public int Status { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 适配工序
|
||||
/// </summary>
|
||||
public long ProcessID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 固资编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string FixedAssetNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备负责人ID
|
||||
/// </summary>
|
||||
public long? ResponsiblePersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备负责人姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string ResponsiblePersonName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大流速
|
||||
/// </summary>
|
||||
public decimal? MaxFlowRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 流速单位
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string FlowRateUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备规格
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Specifications { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 制造商
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Manufacturer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 购买日期
|
||||
/// </summary>
|
||||
public DateTime? PurchaseDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 保修期(月)
|
||||
/// </summary>
|
||||
public int? WarrantyMonths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后维护日期
|
||||
/// </summary>
|
||||
public DateTime? LastMaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次维护日期
|
||||
/// </summary>
|
||||
public DateTime? NextMaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后校验日期
|
||||
/// </summary>
|
||||
public DateTime? LastCalibrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次校验日期
|
||||
/// </summary>
|
||||
public DateTime? NextCalibrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备位置
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态枚举
|
||||
/// </summary>
|
||||
public static class EquipmentStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常
|
||||
/// </summary>
|
||||
public const int Normal = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 维护
|
||||
/// </summary>
|
||||
public const int Maintenance = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 校验
|
||||
/// </summary>
|
||||
public const int Calibration = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 故障
|
||||
/// </summary>
|
||||
public const int Fault = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 报废
|
||||
/// </summary>
|
||||
public const int Scrapped = 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型枚举
|
||||
/// </summary>
|
||||
public static class EquipmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// 生产设备
|
||||
/// </summary>
|
||||
public const string Production = "Production";
|
||||
|
||||
/// <summary>
|
||||
/// 检测设备
|
||||
/// </summary>
|
||||
public const string Testing = "Testing";
|
||||
|
||||
/// <summary>
|
||||
/// 实验室设备
|
||||
/// </summary>
|
||||
public const string Laboratory = "Laboratory";
|
||||
|
||||
/// <summary>
|
||||
/// 办公设备
|
||||
/// </summary>
|
||||
public const string Office = "Office";
|
||||
|
||||
/// <summary>
|
||||
/// 其他设备
|
||||
/// </summary>
|
||||
public const string Other = "Other";
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备维修实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.AEMTableNamePrefix + "equipment_maintenance")]
|
||||
[Index("idx_{tablename}_01", nameof(TenantId) + "," + nameof(EquipmentId) + "," + nameof(MaintenanceDate))]
|
||||
[Index("idx_{tablename}_02", nameof(TenantId) + "," + nameof(MaintenanceType))]
|
||||
[Index("idx_{tablename}_03", nameof(TenantId) + "," + nameof(Status))]
|
||||
public partial class EquipmentMaintenanceEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long EquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string EquipmentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string MaintenanceType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修日期
|
||||
/// </summary>
|
||||
public DateTime MaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修开始时间
|
||||
/// </summary>
|
||||
public DateTime? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修结束时间
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修时长(小时)
|
||||
/// </summary>
|
||||
public decimal? MaintenanceHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修人员ID
|
||||
/// </summary>
|
||||
public long? MaintenancePersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修人员姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string MaintenancePersonName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修内容
|
||||
/// </summary>
|
||||
[Column(StringLength = 1000)]
|
||||
public string MaintenanceContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修结果
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string MaintenanceResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修费用
|
||||
/// </summary>
|
||||
public decimal? MaintenanceCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(0-计划中,1-进行中,2-已完成,3-已取消)
|
||||
/// </summary>
|
||||
public int Status { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否计划维修
|
||||
/// </summary>
|
||||
public bool IsPlanned { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 计划维修周期(天)
|
||||
/// </summary>
|
||||
public int? PlannedCycle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次计划维修日期
|
||||
/// </summary>
|
||||
public DateTime? NextPlannedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修工具
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string MaintenanceTools { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维修材料
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string MaintenanceMaterials { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 维修类型枚举
|
||||
/// </summary>
|
||||
public static class MaintenanceType
|
||||
{
|
||||
/// <summary>
|
||||
/// 预防性维护
|
||||
/// </summary>
|
||||
public const string Preventive = "Preventive";
|
||||
|
||||
/// <summary>
|
||||
/// 故障维修
|
||||
/// </summary>
|
||||
public const string Corrective = "Corrective";
|
||||
|
||||
/// <summary>
|
||||
/// 紧急维修
|
||||
/// </summary>
|
||||
public const string Emergency = "Emergency";
|
||||
|
||||
/// <summary>
|
||||
/// 定期保养
|
||||
/// </summary>
|
||||
public const string Regular = "Regular";
|
||||
|
||||
/// <summary>
|
||||
/// 升级改造
|
||||
/// </summary>
|
||||
public const string Upgrade = "Upgrade";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 维修状态枚举
|
||||
/// </summary>
|
||||
public static class MaintenanceStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 计划中
|
||||
/// </summary>
|
||||
public const int Planned = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 进行中
|
||||
/// </summary>
|
||||
public const int InProgress = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
public const int Completed = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 已取消
|
||||
/// </summary>
|
||||
public const int Cancelled = 3;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备校验仓储接口(简化版本,专用于SmartSchedule模块)
|
||||
/// </summary>
|
||||
public interface IEquipmentCalibrationRepository : IRepositoryBase<EquipmentCalibrationEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据设备ID获取校验记录
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <returns>校验记录列表</returns>
|
||||
Task<List<EquipmentCalibrationEntity>> GetByEquipmentIdAsync(long equipmentId);
|
||||
|
||||
/// <summary>
|
||||
/// 检查设备是否有进行中的校验
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <returns>是否有进行中的校验</returns>
|
||||
Task<bool> HasInProgressCalibrationAsync(long equipmentId);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期需要校验的设备ID列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>设备ID列表</returns>
|
||||
Task<List<long>> GetCalibrationEquipmentIdsAsync(DateTime date);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备维护仓储接口(简化版本,专用于SmartSchedule模块)
|
||||
/// </summary>
|
||||
public interface IEquipmentMaintenanceRepository : IRepositoryBase<EquipmentMaintenanceEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据设备ID获取维护记录
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <returns>维护记录列表</returns>
|
||||
Task<List<EquipmentMaintenanceEntity>> GetByEquipmentIdAsync(long equipmentId);
|
||||
|
||||
/// <summary>
|
||||
/// 检查设备是否有进行中的维护
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <returns>是否有进行中的维护</returns>
|
||||
Task<bool> HasInProgressMaintenanceAsync(long equipmentId);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期需要维护的设备ID列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>设备ID列表</returns>
|
||||
Task<List<long>> GetMaintenanceEquipmentIdsAsync(DateTime date);
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备仓储接口
|
||||
/// </summary>
|
||||
public interface IEquipmentRepository : IRepositoryBase<EquipmentEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据设备类型获取设备列表
|
||||
/// </summary>
|
||||
/// <param name="equipmentType">设备类型</param>
|
||||
/// <returns>设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetByTypeAsync(string equipmentType);
|
||||
|
||||
/// <summary>
|
||||
/// 根据状态获取设备列表
|
||||
/// </summary>
|
||||
/// <param name="status">设备状态</param>
|
||||
/// <returns>设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetByStatusAsync(int status);
|
||||
|
||||
/// <summary>
|
||||
/// 根据内部编号获取设备
|
||||
/// </summary>
|
||||
/// <param name="internalNumber">内部编号</param>
|
||||
/// <returns>设备信息</returns>
|
||||
Task<EquipmentEntity> GetByInternalNumberAsync(string internalNumber);
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用设备列表(正常状态)
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>可用设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetAvailableEquipmentAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 根据工序获取适配设备列表
|
||||
/// </summary>
|
||||
/// <param name="processName">工序名称</param>
|
||||
/// <returns>适配设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetByProcessAsync(string processName);
|
||||
|
||||
/// <summary>
|
||||
/// 检查设备是否可用
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>是否可用</returns>
|
||||
Task<bool> IsEquipmentAvailableAsync(long equipmentId, DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备使用情况
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>设备使用情况</returns>
|
||||
Task<EquipmentUsageInfo> GetUsageAsync(long equipmentId, DateTime startDate, DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 获取需要维护的设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要维护的设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetNeedMaintenanceAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取需要校验的设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要校验的设备列表</returns>
|
||||
Task<List<EquipmentEntity>> GetNeedCalibrationAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定设备类型是否有可用设备
|
||||
/// </summary>
|
||||
/// <param name="equipmentType">设备类型</param>
|
||||
/// <returns>是否有可用设备</returns>
|
||||
Task<bool> HasAvailableEquipmentByTypeAsync(string equipmentType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备使用情况信息
|
||||
/// </summary>
|
||||
public class EquipmentUsageInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long EquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
public string EquipmentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用天数
|
||||
/// </summary>
|
||||
public int UsageDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用小时数
|
||||
/// </summary>
|
||||
public int UsageHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护次数
|
||||
/// </summary>
|
||||
public int MaintenanceCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验次数
|
||||
/// </summary>
|
||||
public int CalibrationCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障次数
|
||||
/// </summary>
|
||||
public int FaultCount { get; set; }
|
||||
}
|
@ -0,0 +1,389 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能整合记录仓储接口
|
||||
///
|
||||
/// 业务思考:
|
||||
/// 1. 提供丰富的查询接口,支持多维度的历史数据分析
|
||||
/// 2. 考虑查询性能,提供必要的分页和索引优化
|
||||
/// 3. 支持统计分析功能,为业务决策提供数据支持
|
||||
/// 4. 考虑数据量增长,提供数据归档和清理机制
|
||||
/// </summary>
|
||||
public interface IIntegrationRecordRepository : IRepositoryBase<IntegrationRecordEntity>
|
||||
{
|
||||
#region 基础查询方法
|
||||
|
||||
/// <summary>
|
||||
/// 根据批次编码获取整合记录
|
||||
/// 业务场景:根据批次编码快速定位特定的整合操作
|
||||
/// </summary>
|
||||
/// <param name="batchCode">批次编码</param>
|
||||
/// <returns>整合记录,如果不存在返回null</returns>
|
||||
Task<IntegrationRecordEntity?> GetByBatchCodeAsync(string batchCode);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定时间范围内的整合记录
|
||||
/// 业务场景:时间范围查询,支持日报、周报、月报等业务需求
|
||||
/// </summary>
|
||||
/// <param name="startTime">开始时间(包含)</param>
|
||||
/// <param name="endTime">结束时间(包含)</param>
|
||||
/// <param name="pageIndex">页码(从1开始)</param>
|
||||
/// <param name="pageSize">每页大小</param>
|
||||
/// <returns>整合记录分页列表</returns>
|
||||
Task<(List<IntegrationRecordEntity> Records, long Total)> GetByTimeRangeAsync(
|
||||
DateTime startTime,
|
||||
DateTime endTime,
|
||||
int pageIndex = 1,
|
||||
int pageSize = 20);
|
||||
|
||||
/// <summary>
|
||||
/// 根据操作人员获取整合记录
|
||||
/// 业务场景:查看特定操作员的整合历史,用于工作量统计和绩效分析
|
||||
/// </summary>
|
||||
/// <param name="operatorUserId">操作员用户ID</param>
|
||||
/// <param name="pageIndex">页码</param>
|
||||
/// <param name="pageSize">每页大小</param>
|
||||
/// <returns>整合记录分页列表</returns>
|
||||
Task<(List<IntegrationRecordEntity> Records, long Total)> GetByOperatorAsync(
|
||||
long operatorUserId,
|
||||
int pageIndex = 1,
|
||||
int pageSize = 20);
|
||||
|
||||
/// <summary>
|
||||
/// 根据项目编号获取相关整合记录
|
||||
/// 业务场景:项目维度的整合历史查询和分析
|
||||
/// </summary>
|
||||
/// <param name="projectNumber">项目编号</param>
|
||||
/// <param name="pageIndex">页码</param>
|
||||
/// <param name="pageSize">每页大小</param>
|
||||
/// <returns>整合记录分页列表</returns>
|
||||
Task<(List<IntegrationRecordEntity> Records, long Total)> GetByProjectNumberAsync(
|
||||
string projectNumber,
|
||||
int pageIndex = 1,
|
||||
int pageSize = 20);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 复合查询方法
|
||||
|
||||
/// <summary>
|
||||
/// 多维度综合查询整合记录
|
||||
/// 业务场景:复杂查询场景,支持多个条件的组合查询
|
||||
/// </summary>
|
||||
/// <param name="operatorUserId">操作员ID(可选)</param>
|
||||
/// <param name="projectNumber">项目编号(可选)</param>
|
||||
/// <param name="integrationType">整合类型(可选)</param>
|
||||
/// <param name="startTime">开始时间(可选)</param>
|
||||
/// <param name="endTime">结束时间(可选)</param>
|
||||
/// <param name="minSuccessRate">最小成功率(可选)</param>
|
||||
/// <param name="pageIndex">页码</param>
|
||||
/// <param name="pageSize">每页大小</param>
|
||||
/// <returns>整合记录分页列表</returns>
|
||||
Task<(List<IntegrationRecordEntity> Records, long Total)> GetByMultipleConditionsAsync(
|
||||
long? operatorUserId = null,
|
||||
string? projectNumber = null,
|
||||
string? integrationType = null,
|
||||
DateTime? startTime = null,
|
||||
DateTime? endTime = null,
|
||||
decimal? minSuccessRate = null,
|
||||
int pageIndex = 1,
|
||||
int pageSize = 20);
|
||||
|
||||
/// <summary>
|
||||
/// 获取包含指定任务的整合记录
|
||||
/// 业务场景:根据任务ID反向查询相关的整合历史
|
||||
/// </summary>
|
||||
/// <param name="taskId">任务ID</param>
|
||||
/// <returns>包含该任务的整合记录列表</returns>
|
||||
Task<List<IntegrationRecordEntity>> GetRecordsContainingTaskAsync(long taskId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 统计分析方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定时间段的整合统计数据
|
||||
/// 业务场景:生成统计报表,分析整合效果和趋势
|
||||
/// </summary>
|
||||
/// <param name="startTime">开始时间</param>
|
||||
/// <param name="endTime">结束时间</param>
|
||||
/// <returns>统计数据</returns>
|
||||
Task<IntegrationStatistics> GetIntegrationStatisticsAsync(DateTime startTime, DateTime endTime);
|
||||
|
||||
/// <summary>
|
||||
/// 获取操作员整合统计数据
|
||||
/// 业务场景:操作员工作量和效率分析
|
||||
/// </summary>
|
||||
/// <param name="operatorUserId">操作员ID</param>
|
||||
/// <param name="startTime">开始时间</param>
|
||||
/// <param name="endTime">结束时间</param>
|
||||
/// <returns>操作员统计数据</returns>
|
||||
Task<OperatorIntegrationStats> GetOperatorStatisticsAsync(
|
||||
long operatorUserId,
|
||||
DateTime startTime,
|
||||
DateTime endTime);
|
||||
|
||||
/// <summary>
|
||||
/// 获取策略效果分析数据
|
||||
/// 业务场景:分析不同分配策略的效果,为策略优化提供数据支持
|
||||
/// </summary>
|
||||
/// <param name="startTime">开始时间</param>
|
||||
/// <param name="endTime">结束时间</param>
|
||||
/// <returns>策略效果统计数据</returns>
|
||||
Task<List<StrategyEffectivenessStats>> GetStrategyEffectivenessAsync(
|
||||
DateTime startTime,
|
||||
DateTime endTime);
|
||||
|
||||
/// <summary>
|
||||
/// 获取整合性能趋势数据
|
||||
/// 业务场景:监控系统性能,识别性能瓶颈和优化机会
|
||||
/// </summary>
|
||||
/// <param name="days">最近天数</param>
|
||||
/// <returns>性能趋势数据</returns>
|
||||
Task<List<IntegrationPerformanceTrend>> GetPerformanceTrendAsync(int days = 30);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务专用方法
|
||||
|
||||
/// <summary>
|
||||
/// 检查批次编码是否已存在
|
||||
/// 业务场景:防止批次编码重复,确保数据唯一性
|
||||
/// </summary>
|
||||
/// <param name="batchCode">批次编码</param>
|
||||
/// <returns>是否存在</returns>
|
||||
Task<bool> BatchCodeExistsAsync(string batchCode);
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近的整合记录
|
||||
/// 业务场景:快速查看最新的整合状态,支持监控面板显示
|
||||
/// </summary>
|
||||
/// <param name="count">获取记录数量</param>
|
||||
/// <returns>最近的整合记录列表</returns>
|
||||
Task<List<IntegrationRecordEntity>> GetRecentRecordsAsync(int count = 10);
|
||||
|
||||
/// <summary>
|
||||
/// 获取失败率高的整合记录
|
||||
/// 业务场景:识别问题操作,支持质量改进和问题排查
|
||||
/// </summary>
|
||||
/// <param name="minFailureRate">最小失败率阈值(百分比)</param>
|
||||
/// <param name="startTime">开始时间</param>
|
||||
/// <param name="endTime">结束时间</param>
|
||||
/// <param name="count">最大返回数量</param>
|
||||
/// <returns>高失败率的整合记录</returns>
|
||||
Task<List<IntegrationRecordEntity>> GetHighFailureRateRecordsAsync(
|
||||
decimal minFailureRate,
|
||||
DateTime startTime,
|
||||
DateTime endTime,
|
||||
int count = 50);
|
||||
|
||||
/// <summary>
|
||||
/// 软删除过期的测试数据
|
||||
/// 业务场景:定期清理测试数据,保持生产环境数据整洁
|
||||
/// </summary>
|
||||
/// <param name="beforeDate">删除此日期之前的测试数据</param>
|
||||
/// <returns>删除的记录数量</returns>
|
||||
Task<int> SoftDeleteExpiredTestDataAsync(DateTime beforeDate);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 统计数据模型
|
||||
|
||||
/// <summary>
|
||||
/// 整合统计数据
|
||||
/// </summary>
|
||||
public class IntegrationStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// 统计时间范围开始
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间范围结束
|
||||
/// </summary>
|
||||
public DateTime EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合操作总次数
|
||||
/// </summary>
|
||||
public int TotalIntegrations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 涉及任务总数
|
||||
/// </summary>
|
||||
public long TotalTasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功分配任务数
|
||||
/// </summary>
|
||||
public long SuccessfulTasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败分配任务数
|
||||
/// </summary>
|
||||
public long FailedTasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均成功率
|
||||
/// </summary>
|
||||
public decimal AverageSuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均执行耗时(毫秒)
|
||||
/// </summary>
|
||||
public long AverageElapsedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均人员公平性评分
|
||||
/// </summary>
|
||||
public decimal AveragePersonnelFairnessScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均设备利用率
|
||||
/// </summary>
|
||||
public decimal AverageEquipmentUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 活跃操作员数量
|
||||
/// </summary>
|
||||
public int ActiveOperatorCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 涉及项目数量
|
||||
/// </summary>
|
||||
public int InvolvedProjectCount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作员整合统计数据
|
||||
/// </summary>
|
||||
public class OperatorIntegrationStats
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作员用户ID
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户名
|
||||
/// </summary>
|
||||
public string OperatorUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作员真实姓名
|
||||
/// </summary>
|
||||
public string OperatorRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 执行整合次数
|
||||
/// </summary>
|
||||
public int IntegrationCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理任务总数
|
||||
/// </summary>
|
||||
public long TotalTasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均成功率
|
||||
/// </summary>
|
||||
public decimal AverageSuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总耗时(毫秒)
|
||||
/// </summary>
|
||||
public long TotalElapsedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均每次整合耗时
|
||||
/// </summary>
|
||||
public long AverageIntegrationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后操作时间
|
||||
/// </summary>
|
||||
public DateTime LastOperationTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 策略效果统计数据
|
||||
/// </summary>
|
||||
public class StrategyEffectivenessStats
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员分配策略
|
||||
/// </summary>
|
||||
public string PersonnelStrategy { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配策略
|
||||
/// </summary>
|
||||
public string EquipmentStrategy { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 使用次数
|
||||
/// </summary>
|
||||
public int UsageCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均成功率
|
||||
/// </summary>
|
||||
public decimal AverageSuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均人员公平性评分
|
||||
/// </summary>
|
||||
public decimal AveragePersonnelFairnessScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均设备利用率
|
||||
/// </summary>
|
||||
public decimal AverageEquipmentUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均执行耗时
|
||||
/// </summary>
|
||||
public long AverageElapsedTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合性能趋势数据
|
||||
/// </summary>
|
||||
public class IntegrationPerformanceTrend
|
||||
{
|
||||
/// <summary>
|
||||
/// 日期
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当日整合次数
|
||||
/// </summary>
|
||||
public int IntegrationCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当日平均成功率
|
||||
/// </summary>
|
||||
public decimal AverageSuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当日平均耗时(毫秒)
|
||||
/// </summary>
|
||||
public long AverageElapsedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当日处理任务总数
|
||||
/// </summary>
|
||||
public long TotalTasks { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录变更详情
|
||||
/// 记录版本间的详细变更信息,支持变更分析和回滚操作
|
||||
/// </summary>
|
||||
public class IntegrationChangeDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// 变更类型列表
|
||||
/// 可能的值:TaskModified, TaskAdded, TaskRemoved, PersonnelChanged, EquipmentChanged,
|
||||
/// TaskTimeConflict, PersonnelUnavailable, EquipmentUnavailable, PriorityAdjusted
|
||||
/// </summary>
|
||||
public List<string> ChangeTypes { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 发生变更的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> ChangedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 新增的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> AddedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 移除的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> RemovedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 受影响的人员ID列表
|
||||
/// </summary>
|
||||
public List<long> AffectedPersonnelIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 受影响的设备ID列表
|
||||
/// </summary>
|
||||
public List<long> AffectedEquipmentIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 具体的任务修改详情
|
||||
/// </summary>
|
||||
public List<TaskChangeDetail> TaskModifications { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配变更详情
|
||||
/// </summary>
|
||||
public List<PersonnelAssignmentChange> PersonnelChanges { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配变更详情
|
||||
/// </summary>
|
||||
public List<EquipmentAssignmentChange> EquipmentChanges { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发的原始事件
|
||||
/// 记录导致变更的原始事件信息
|
||||
/// </summary>
|
||||
public ChangeTriggeredEvent TriggerEvent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 变更检测时间
|
||||
/// </summary>
|
||||
public DateTime DetectedTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 变更处理状态
|
||||
/// Detected-已检测, Processing-处理中, Completed-已完成, Failed-处理失败
|
||||
/// </summary>
|
||||
public string ProcessingStatus { get; set; } = "Detected";
|
||||
|
||||
/// <summary>
|
||||
/// 变更影响分析
|
||||
/// </summary>
|
||||
public ChangeImpactAnalysis ImpactAnalysis { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务变更详情(Domain层)
|
||||
/// </summary>
|
||||
public class TaskChangeDetail
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 修改类型
|
||||
/// TimeChanged-时间变更, PriorityChanged-优先级变更, PersonnelRequirementChanged-人员需求变更,
|
||||
/// EquipmentRequirementChanged-设备需求变更, StatusChanged-状态变更
|
||||
/// </summary>
|
||||
public string ModificationType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 修改前的值(JSON格式)
|
||||
/// </summary>
|
||||
public string BeforeValue { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 修改后的值(JSON格式)
|
||||
/// </summary>
|
||||
public string AfterValue { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 修改时间
|
||||
/// </summary>
|
||||
public DateTime ModifiedTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 修改说明
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 影响评估
|
||||
/// 评估这个修改对整体分配的影响程度
|
||||
/// </summary>
|
||||
public string ImpactAssessment { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更类型(兼容性属性,映射到ModificationType)
|
||||
/// </summary>
|
||||
public string ChangeType => ModificationType;
|
||||
|
||||
/// <summary>
|
||||
/// 影响级别(根据ImpactAssessment计算)
|
||||
/// </summary>
|
||||
public TaskChangeImpactLevel ImpactLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ImpactAssessment.Contains("高影响") || ImpactAssessment.Contains("严重"))
|
||||
return TaskChangeImpactLevel.High;
|
||||
if (ImpactAssessment.Contains("中等") || ImpactAssessment.Contains("一般"))
|
||||
return TaskChangeImpactLevel.Medium;
|
||||
if (ImpactAssessment.Contains("低影响") || ImpactAssessment.Contains("轻微"))
|
||||
return TaskChangeImpactLevel.Low;
|
||||
return TaskChangeImpactLevel.Medium; // 默认中等影响
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配变更
|
||||
/// </summary>
|
||||
public class PersonnelAssignmentChange
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原分配人员ID
|
||||
/// </summary>
|
||||
public long? PreviousPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原分配人员姓名
|
||||
/// </summary>
|
||||
public string PreviousPersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 新分配人员ID
|
||||
/// </summary>
|
||||
public long? NewPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新分配人员姓名
|
||||
/// </summary>
|
||||
public string NewPersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更原因
|
||||
/// </summary>
|
||||
public string ChangeReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更时间
|
||||
/// </summary>
|
||||
public DateTime ChangeTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为自动变更
|
||||
/// </summary>
|
||||
public bool IsAutomaticChange { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配变更
|
||||
/// </summary>
|
||||
public class EquipmentAssignmentChange
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原分配设备ID
|
||||
/// </summary>
|
||||
public long? PreviousEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原分配设备名称
|
||||
/// </summary>
|
||||
public string PreviousEquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 新分配设备ID
|
||||
/// </summary>
|
||||
public long? NewEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新分配设备名称
|
||||
/// </summary>
|
||||
public string NewEquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更原因
|
||||
/// </summary>
|
||||
public string ChangeReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更时间
|
||||
/// </summary>
|
||||
public DateTime ChangeTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为自动变更
|
||||
/// </summary>
|
||||
public bool IsAutomaticChange { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发事件
|
||||
/// </summary>
|
||||
public class ChangeTriggeredEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件类型
|
||||
/// TaskModified-任务修改, UserRequest-用户请求, SystemOptimization-系统优化,
|
||||
/// ResourceUnavailable-资源不可用, ConflictDetected-冲突检测
|
||||
/// </summary>
|
||||
public string EventType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 事件来源
|
||||
/// 标识触发变更的具体来源
|
||||
/// </summary>
|
||||
public string EventSource { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 事件详情
|
||||
/// </summary>
|
||||
public string EventDetails { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 事件发生时间
|
||||
/// </summary>
|
||||
public DateTime EventTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 触发用户ID
|
||||
/// </summary>
|
||||
public long? TriggeredByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发用户姓名
|
||||
/// </summary>
|
||||
public string TriggeredByUserName { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变更影响分析
|
||||
/// </summary>
|
||||
public class ChangeImpactAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 影响范围
|
||||
/// Local-局部影响, Regional-区域影响, Global-全局影响
|
||||
/// </summary>
|
||||
public string ImpactScope { get; set; } = "Local";
|
||||
|
||||
/// <summary>
|
||||
/// 影响严重程度
|
||||
/// Low-轻微, Medium-中等, High-严重, Critical-关键
|
||||
/// </summary>
|
||||
public string SeverityLevel { get; set; } = "Low";
|
||||
|
||||
/// <summary>
|
||||
/// 预计影响的任务数量
|
||||
/// </summary>
|
||||
public int EstimatedAffectedTasks { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 预计影响的人员数量
|
||||
/// </summary>
|
||||
public int EstimatedAffectedPersonnel { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 预计影响的设备数量
|
||||
/// </summary>
|
||||
public int EstimatedAffectedEquipment { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 建议的处理策略
|
||||
/// AutoReallocation-自动重新分配, ManualReview-手动复审, FullReintegration-完全重新整合
|
||||
/// </summary>
|
||||
public string RecommendedAction { get; set; } = "AutoReallocation";
|
||||
|
||||
/// <summary>
|
||||
/// 预计处理耗时(分钟)
|
||||
/// </summary>
|
||||
public int EstimatedProcessingTimeMinutes { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 风险评估
|
||||
/// </summary>
|
||||
public string RiskAssessment { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 业务影响说明
|
||||
/// </summary>
|
||||
public string BusinessImpactDescription { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合生命周期阶段枚举
|
||||
/// 定义整合记录在其生命周期中所处的不同阶段
|
||||
/// </summary>
|
||||
public enum IntegrationLifecycleStage
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建阶段 - 刚创建,正在初始化
|
||||
/// </summary>
|
||||
Created = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 草稿阶段 - 正在编辑和完善
|
||||
/// </summary>
|
||||
Draft = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 验证阶段 - 正在进行验证检查
|
||||
/// </summary>
|
||||
Validating = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 准备发布 - 验证通过,准备发布
|
||||
/// </summary>
|
||||
ReadyToPublish = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 已发布 - 正式发布,开始执行
|
||||
/// </summary>
|
||||
Published = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 执行中 - 正在执行任务
|
||||
/// </summary>
|
||||
InProgress = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 部分完成 - 部分任务已完成
|
||||
/// </summary>
|
||||
PartiallyCompleted = 7,
|
||||
|
||||
/// <summary>
|
||||
/// 已完成 - 所有任务都已完成
|
||||
/// </summary>
|
||||
Completed = 8,
|
||||
|
||||
/// <summary>
|
||||
/// 已暂停 - 执行被暂停
|
||||
/// </summary>
|
||||
Paused = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 已取消 - 整合被取消
|
||||
/// </summary>
|
||||
Cancelled = 10,
|
||||
|
||||
/// <summary>
|
||||
/// 已过期 - 超过有效期限
|
||||
/// </summary>
|
||||
Expired = 11,
|
||||
|
||||
/// <summary>
|
||||
/// 已归档 - 归档保存
|
||||
/// </summary>
|
||||
Archived = 12,
|
||||
|
||||
/// <summary>
|
||||
/// 错误状态 - 出现错误需要处理
|
||||
/// </summary>
|
||||
Error = 99
|
||||
}
|
||||
}
|
@ -0,0 +1,721 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能整合记录实体
|
||||
/// 用于记录每次智能任务整合的完整过程和结果
|
||||
///
|
||||
/// 业务思考:
|
||||
/// 1. 作为重要的业务审计数据,需要完整记录整合的全过程
|
||||
/// 2. 支持多租户模式,确保数据安全隔离
|
||||
/// 3. 提供丰富的查询维度,支持历史分析和决策支持
|
||||
/// 4. 考虑JSON存储复杂结果数据,平衡存储效率和查询性能
|
||||
/// </summary>
|
||||
[Table(Name = "sse_integration_record")]
|
||||
[Index("idx_integration_batch_code", "IntegrationBatchCode", true)] // 批次编码唯一索引
|
||||
[Index("idx_integration_time", "IntegrationTime")] // 时间索引,支持时间范围查询
|
||||
[Index("idx_operator", "OperatorUserId")] // 操作员索引
|
||||
[Index("idx_tenant_time", "TenantId,IntegrationTime")] // 租户+时间组合索引
|
||||
public class IntegrationRecordEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合批次编码
|
||||
/// 格式:INT + yyyyMMddHHmmss + XXX,如:INT20240314143025123
|
||||
/// 业务意义:唯一标识一次整合操作,便于追踪和关联
|
||||
/// </summary>
|
||||
[Column(StringLength = 30)]
|
||||
[Required(ErrorMessage = "整合批次编码不能为空")]
|
||||
public string IntegrationBatchCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合执行时间
|
||||
/// 记录实际执行整合操作的时间点
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime IntegrationTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 操作人员用户ID
|
||||
/// 关联到系统用户表,记录执行整合的操作员
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "操作人员ID不能为空")]
|
||||
public long OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人员用户名
|
||||
/// 冗余存储,提高查询性能,避免频繁关联用户表
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required(ErrorMessage = "操作人员用户名不能为空")]
|
||||
public string OperatorUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作人员真实姓名
|
||||
/// 用于业务场景下的可读性显示
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required(ErrorMessage = "操作人员姓名不能为空")]
|
||||
public string OperatorRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合的任务ID列表(JSON格式存储)
|
||||
/// 存储格式:[1,2,3,4,5]
|
||||
/// 业务意义:记录本次整合涉及的所有任务,支持反向查询
|
||||
/// </summary>
|
||||
[Column(DbType = "longtext")]
|
||||
[Required(ErrorMessage = "任务ID列表不能为空")]
|
||||
public string TaskIdsJson { get; set; } = "[]";
|
||||
|
||||
/// <summary>
|
||||
/// 整合策略配置(JSON格式存储)
|
||||
/// 包含:人员分配策略、设备分配策略、各种配置参数
|
||||
/// 业务价值:记录决策依据,支持策略效果分析和优化
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
[Required]
|
||||
public string StrategyConfigJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配结果详情(JSON格式存储)
|
||||
/// 包含:成功匹配列表、失败原因、工作负载分析等
|
||||
/// 存储完整的PersonnelAllocationResult对象
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string PersonnelAllocationResultJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配结果详情(JSON格式存储)
|
||||
/// 包含:成功匹配列表、失败原因、利用率分析等
|
||||
/// 存储完整的EquipmentAllocationResult对象
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string EquipmentAllocationResultJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 成功分配的任务数量
|
||||
/// 统计字段,提高查询性能
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int SuccessTaskCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 分配失败的任务数量
|
||||
/// 统计字段,用于成功率计算和分析
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int FailedTaskCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 整合执行总耗时(毫秒)
|
||||
/// 性能监控指标,用于系统优化分析
|
||||
/// </summary>
|
||||
[Required]
|
||||
public long ElapsedMilliseconds { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配公平性评分(0-100)
|
||||
/// 业务指标,评估人员工作负载分配的公平程度
|
||||
/// </summary>
|
||||
public int PersonnelFairnessScore { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 设备整体利用率(百分比,保留1位小数)
|
||||
/// 业务指标,评估设备资源利用效率
|
||||
/// </summary>
|
||||
[Column(DbType = "decimal(5,1)")]
|
||||
public decimal EquipmentUtilizationRate { get; set; } = 0.0m;
|
||||
|
||||
/// <summary>
|
||||
/// 整合结果摘要描述
|
||||
/// 简洁的文本描述,便于快速了解整合结果
|
||||
/// 示例:总任务数: 25, 成功: 23, 失败: 2, 成功率: 92%
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string ResultSummary { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 失败原因分类统计(JSON格式存储)
|
||||
/// 格式:{"PersonnelAllocationFailed": 2, "EquipmentAllocationFailed": 1}
|
||||
/// 业务价值:支持失败原因分析和系统改进
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string FailureReasonStats { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 涉及的项目编号列表(逗号分隔)
|
||||
/// 便于按项目查询整合历史,支持项目级别的数据分析
|
||||
/// 示例:PRJ001,PRJ002,PRJ003
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string ProjectNumbers { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合类型
|
||||
/// 标识整合的触发方式:Manual-手动触发, Scheduled-定时触发, Auto-自动触发
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
[Required]
|
||||
public string IntegrationType { get; set; } = "Manual";
|
||||
|
||||
/// <summary>
|
||||
/// 业务备注信息
|
||||
/// 操作员填写的备注,记录特殊情况或业务背景
|
||||
/// </summary>
|
||||
[Column(StringLength = 1000)]
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为测试数据
|
||||
/// 区分生产数据和测试数据,便于数据清理和分析
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool IsTestData { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 数据版本号
|
||||
/// 支持数据结构演进和向后兼容
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int DataVersion { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录发布状态
|
||||
/// 控制整合记录的生命周期管理
|
||||
/// Draft-草稿, Published-已发布, Completed-已完成, Cancelled-已撤销
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
[Required]
|
||||
public string PublishStatus { get; set; } = IntegrationRecordPublishStatus.Draft;
|
||||
|
||||
/// <summary>
|
||||
/// 发布时间
|
||||
/// 记录正式发布生效的时间点
|
||||
/// </summary>
|
||||
public DateTime? PublishedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员用户ID
|
||||
/// 记录执行发布操作的用户,可能与创建者不同
|
||||
/// </summary>
|
||||
public long? PublishedByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员用户名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string PublishedByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员真实姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string PublishedByRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发布说明
|
||||
/// 记录发布时的业务说明或特殊情况备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string PublishRemarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 完成时间
|
||||
/// 所有任务执行完毕的时间点
|
||||
/// </summary>
|
||||
public DateTime? CompletedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销时间
|
||||
/// 记录被撤销的时间点
|
||||
/// </summary>
|
||||
public DateTime? CancelledTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销操作员用户ID
|
||||
/// </summary>
|
||||
public long? CancelledByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销操作员用户名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string CancelledByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销原因
|
||||
/// 记录撤销的具体原因和说明
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string CancelReason { get; set; } = string.Empty;
|
||||
|
||||
#region 版本管理和变更追踪扩展字段
|
||||
|
||||
/// <summary>
|
||||
/// 当前版本号
|
||||
/// 每次修改后自增,用于版本管理和冲突检测
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int CurrentVersion { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 父版本ID
|
||||
/// 指向上一个版本的整合记录,构建版本链
|
||||
/// null表示这是初始版本
|
||||
/// </summary>
|
||||
public long? ParentVersionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 根版本ID
|
||||
/// 指向版本链的根节点,用于快速定位同一整合记录的所有版本
|
||||
/// </summary>
|
||||
[Required]
|
||||
public long RootVersionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本创建原因
|
||||
/// 记录为什么创建这个新版本:TaskModified-任务修改, ManualAdjustment-手动调整, SystemReallocation-系统重新分配
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string VersionReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更摘要
|
||||
/// 简述本版本相对于上一版本的主要变更内容
|
||||
/// </summary>
|
||||
[Column(StringLength = 1000)]
|
||||
public string ChangeSummary { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更详情JSON
|
||||
/// 存储详细的变更信息,包括变更类型、影响的任务、前后对比等
|
||||
/// 格式:{"changedTasks": [...], "modifications": [...], "affectedPersonnel": [...]}
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string ChangeDetailsJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 是否为活跃版本
|
||||
/// true表示这是当前生效的版本,每个根版本只能有一个活跃版本
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool IsActiveVersion { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发源
|
||||
/// 记录变更的触发来源:TaskChange-任务变更, UserModification-用户修改, SystemOptimization-系统优化
|
||||
/// </summary>
|
||||
[Column(StringLength = 30)]
|
||||
public string ChangeTriggerSource { get; set; } = "Initial";
|
||||
|
||||
/// <summary>
|
||||
/// 原始任务数量
|
||||
/// 记录初始分配时的任务数量,用于对比分析
|
||||
/// </summary>
|
||||
public int OriginalTaskCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 变更影响评分
|
||||
/// 0-100分,评估本次变更对整体分配方案的影响程度
|
||||
/// </summary>
|
||||
public int ChangeImpactScore { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 自动重新分配标志
|
||||
/// 标记是否可以自动进行重新分配,还是需要人工干预
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool AllowAutoReallocation { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 上次检查变更时间
|
||||
/// 用于变更检测和增量更新机制
|
||||
/// </summary>
|
||||
public DateTime? LastChangeCheckTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 快照数据JSON
|
||||
/// 存储关键业务数据的快照,用于版本对比和回滚
|
||||
/// 包含:任务分配快照、人员工作负载快照、设备利用率快照等
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string SnapshotDataJson { get; set; } = "{}";
|
||||
|
||||
#endregion
|
||||
|
||||
#region 计算属性
|
||||
|
||||
/// <summary>
|
||||
/// 整合成功率(计算属性)
|
||||
/// 返回成功率百分比,保留1位小数
|
||||
/// </summary>
|
||||
[Navigate(nameof(SuccessTaskCount))]
|
||||
public decimal SuccessRate
|
||||
{
|
||||
get
|
||||
{
|
||||
var totalTasks = SuccessTaskCount + FailedTaskCount;
|
||||
return totalTasks > 0 ? Math.Round((decimal)SuccessTaskCount / totalTasks * 100, 1) : 0;
|
||||
}
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务总数(计算属性)
|
||||
/// </summary>
|
||||
[Navigate(nameof(SuccessTaskCount))]
|
||||
public int TotalTaskCount
|
||||
{
|
||||
get => SuccessTaskCount + FailedTaskCount;
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整体匹配成功率(计算属性)
|
||||
/// </summary>
|
||||
public decimal OverallMatchSuccessRate => SuccessRate / 100;
|
||||
|
||||
/// <summary>
|
||||
/// 平均任务复杂度(计算属性)
|
||||
/// </summary>
|
||||
public decimal AverageTaskComplexity => 2.5m; // 暂时使用固定值
|
||||
|
||||
/// <summary>
|
||||
/// 平均每任务耗时(计算属性)
|
||||
/// 返回毫秒数,用于性能分析
|
||||
/// </summary>
|
||||
[Navigate(nameof(ElapsedMilliseconds))]
|
||||
public long AverageTimePerTask
|
||||
{
|
||||
get
|
||||
{
|
||||
var totalTasks = TotalTaskCount;
|
||||
return totalTasks > 0 ? ElapsedMilliseconds / totalTasks : 0;
|
||||
}
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务方法
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化任务ID列表
|
||||
/// 将JSON格式的TaskIdsJson转换为List<long>
|
||||
/// </summary>
|
||||
public List<long> GetTaskIds()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TaskIdsJson))
|
||||
return new List<long>();
|
||||
|
||||
// 优先尝试JSON反序列化
|
||||
try
|
||||
{
|
||||
return System.Text.Json.JsonSerializer.Deserialize<List<long>>(TaskIdsJson) ?? new List<long>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 兼容旧格式(逗号分隔)
|
||||
return TaskIdsJson.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Trim())
|
||||
.Where(p => !string.IsNullOrEmpty(p))
|
||||
.Select(long.Parse)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new List<long>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置任务ID列表
|
||||
/// 将List<long>序列化为JSON存储
|
||||
/// </summary>
|
||||
public void SetTaskIds(List<long> taskIds)
|
||||
{
|
||||
TaskIdsJson = System.Text.Json.JsonSerializer.Serialize(taskIds ?? new List<long>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取项目编号列表
|
||||
/// 将逗号分隔的项目编号字符串转换为列表
|
||||
/// </summary>
|
||||
public List<string> GetProjectNumbers()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ProjectNumbers))
|
||||
return new List<string>();
|
||||
|
||||
return ProjectNumbers.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Trim())
|
||||
.Where(p => !string.IsNullOrEmpty(p))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置项目编号列表
|
||||
/// 将列表转换为逗号分隔的字符串存储
|
||||
/// </summary>
|
||||
public void SetProjectNumbers(List<string> projectNumbers)
|
||||
{
|
||||
if (projectNumbers == null || !projectNumbers.Any())
|
||||
{
|
||||
ProjectNumbers = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectNumbers = string.Join(",", projectNumbers.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新统计信息
|
||||
/// 根据分配结果更新各项统计字段
|
||||
/// </summary>
|
||||
public void UpdateStatistics(int successCount, int failedCount, long elapsedMs, int fairnessScore, decimal utilizationRate)
|
||||
{
|
||||
SuccessTaskCount = successCount;
|
||||
FailedTaskCount = failedCount;
|
||||
ElapsedMilliseconds = elapsedMs;
|
||||
PersonnelFairnessScore = fairnessScore;
|
||||
EquipmentUtilizationRate = utilizationRate;
|
||||
|
||||
ResultSummary = $"总任务数: {TotalTaskCount}, 成功: {SuccessTaskCount}, 失败: {FailedTaskCount}, 成功率: {SuccessRate}%";
|
||||
}
|
||||
|
||||
#region 版本管理业务方法
|
||||
|
||||
/// <summary>
|
||||
/// 创建新版本
|
||||
/// 基于当前版本创建一个新的版本记录,用于变更追踪
|
||||
/// </summary>
|
||||
/// <param name="reason">版本创建原因</param>
|
||||
/// <param name="changeSummary">变更摘要</param>
|
||||
/// <param name="operatorUserId">操作员用户ID</param>
|
||||
/// <param name="operatorName">操作员姓名</param>
|
||||
/// <returns>新版本的整合记录实体</returns>
|
||||
public IntegrationRecordEntity CreateNewVersion(string reason, string changeSummary, long operatorUserId, string operatorName)
|
||||
{
|
||||
var newVersion = new IntegrationRecordEntity
|
||||
{
|
||||
// 继承基本信息
|
||||
IntegrationBatchCode = this.IntegrationBatchCode,
|
||||
TenantId = this.TenantId,
|
||||
RootVersionId = this.RootVersionId == 0 ? this.Id : this.RootVersionId,
|
||||
ParentVersionId = this.Id,
|
||||
CurrentVersion = this.CurrentVersion + 1,
|
||||
|
||||
// 版本变更信息
|
||||
VersionReason = reason,
|
||||
ChangeSummary = changeSummary,
|
||||
ChangeTriggerSource = reason,
|
||||
IsActiveVersion = true, // 新版本为活跃版本
|
||||
|
||||
// 操作员信息
|
||||
OperatorUserId = operatorUserId,
|
||||
OperatorUserName = operatorName,
|
||||
OperatorRealName = operatorName,
|
||||
IntegrationTime = DateTime.Now,
|
||||
|
||||
// 继承配置信息
|
||||
StrategyConfigJson = this.StrategyConfigJson,
|
||||
IntegrationType = this.IntegrationType,
|
||||
|
||||
// 继承发布状态相关信息
|
||||
PublishStatus = this.PublishStatus,
|
||||
PublishedTime = this.PublishedTime,
|
||||
PublishedByUserId = this.PublishedByUserId,
|
||||
PublishedByUserName = this.PublishedByUserName,
|
||||
PublishedByRealName = this.PublishedByRealName,
|
||||
PublishRemarks = this.PublishRemarks,
|
||||
|
||||
// 初始化新版本的其他字段
|
||||
TaskIdsJson = "[]",
|
||||
PersonnelAllocationResultJson = "{}",
|
||||
EquipmentAllocationResultJson = "{}",
|
||||
FailureReasonStats = "{}",
|
||||
ChangeDetailsJson = "{}",
|
||||
SnapshotDataJson = "{}",
|
||||
DataVersion = this.DataVersion,
|
||||
AllowAutoReallocation = true,
|
||||
LastChangeCheckTime = DateTime.Now
|
||||
};
|
||||
|
||||
// 当前版本标记为非活跃
|
||||
this.IsActiveVersion = false;
|
||||
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取变更详情
|
||||
/// 解析ChangeDetailsJson并返回结构化的变更详情
|
||||
/// </summary>
|
||||
public IntegrationChangeDetails GetChangeDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ChangeDetailsJson) || ChangeDetailsJson == "{}")
|
||||
return new IntegrationChangeDetails();
|
||||
|
||||
return System.Text.Json.JsonSerializer.Deserialize<IntegrationChangeDetails>(ChangeDetailsJson)
|
||||
?? new IntegrationChangeDetails();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new IntegrationChangeDetails();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置变更详情
|
||||
/// 将变更详情对象序列化为JSON存储
|
||||
/// </summary>
|
||||
public void SetChangeDetails(IntegrationChangeDetails changeDetails)
|
||||
{
|
||||
ChangeDetailsJson = System.Text.Json.JsonSerializer.Serialize(changeDetails ?? new IntegrationChangeDetails());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取快照数据
|
||||
/// 解析SnapshotDataJson并返回快照数据对象
|
||||
/// </summary>
|
||||
public IntegrationSnapshot GetSnapshotData()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(SnapshotDataJson) || SnapshotDataJson == "{}")
|
||||
return new IntegrationSnapshot();
|
||||
|
||||
return System.Text.Json.JsonSerializer.Deserialize<IntegrationSnapshot>(SnapshotDataJson)
|
||||
?? new IntegrationSnapshot();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new IntegrationSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置快照数据
|
||||
/// 将快照数据对象序列化为JSON存储
|
||||
/// </summary>
|
||||
public void SetSnapshotData(IntegrationSnapshot snapshotData)
|
||||
{
|
||||
SnapshotDataJson = System.Text.Json.JsonSerializer.Serialize(snapshotData ?? new IntegrationSnapshot());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算变更影响评分
|
||||
/// 基于变更的任务数量、人员影响、设备影响等计算影响评分
|
||||
/// </summary>
|
||||
public int CalculateChangeImpactScore(IntegrationChangeDetails changeDetails)
|
||||
{
|
||||
if (changeDetails == null) return 0;
|
||||
|
||||
int score = 0;
|
||||
int totalTasks = TotalTaskCount > 0 ? TotalTaskCount : 1;
|
||||
|
||||
// 基于变更任务比例计算基础分数 (40%)
|
||||
var changedTaskRatio = (double)changeDetails.ChangedTaskIds.Count / totalTasks;
|
||||
score += (int)(changedTaskRatio * 40);
|
||||
|
||||
// 基于人员变更数量计算分数 (30%)
|
||||
var personnelChangeRatio = Math.Min(1.0, (double)changeDetails.AffectedPersonnelIds.Count / 10);
|
||||
score += (int)(personnelChangeRatio * 30);
|
||||
|
||||
// 基于设备变更数量计算分数 (20%)
|
||||
var equipmentChangeRatio = Math.Min(1.0, (double)changeDetails.AffectedEquipmentIds.Count / 10);
|
||||
score += (int)(equipmentChangeRatio * 20);
|
||||
|
||||
// 基于变更类型的严重程度 (10%)
|
||||
var severityScore = changeDetails.ChangeTypes.Contains("TaskTimeConflict") ? 10 :
|
||||
changeDetails.ChangeTypes.Contains("PersonnelUnavailable") ? 8 :
|
||||
changeDetails.ChangeTypes.Contains("EquipmentUnavailable") ? 6 : 2;
|
||||
score += severityScore;
|
||||
|
||||
return Math.Min(100, Math.Max(0, score));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否需要重新分配
|
||||
/// 基于变更影响评分和业务规则判断是否需要重新分配
|
||||
/// </summary>
|
||||
public bool ShouldTriggerReallocation()
|
||||
{
|
||||
// 如果不允许自动重新分配,返回false
|
||||
if (!AllowAutoReallocation) return false;
|
||||
|
||||
// 如果变更影响评分超过阈值,需要重新分配
|
||||
if (ChangeImpactScore >= 30) return true;
|
||||
|
||||
// 如果有任务时间冲突,必须重新分配
|
||||
var changeDetails = GetChangeDetails();
|
||||
if (changeDetails.ChangeTypes.Contains("TaskTimeConflict")) return true;
|
||||
|
||||
// 如果有关键人员不可用,需要重新分配
|
||||
if (changeDetails.ChangeTypes.Contains("PersonnelUnavailable")) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合类型枚举
|
||||
/// </summary>
|
||||
public static class IntegrationType
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动触发
|
||||
/// </summary>
|
||||
public const string Manual = "Manual";
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发
|
||||
/// </summary>
|
||||
public const string Scheduled = "Scheduled";
|
||||
|
||||
/// <summary>
|
||||
/// 自动触发
|
||||
/// </summary>
|
||||
public const string Auto = "Auto";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录发布状态枚举
|
||||
/// 定义整合记录的生命周期状态
|
||||
/// </summary>
|
||||
public static class IntegrationRecordPublishStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 草稿状态 - 刚生成的整合记录,未正式生效
|
||||
/// </summary>
|
||||
public const string Draft = "Draft";
|
||||
|
||||
/// <summary>
|
||||
/// 已发布状态 - 已发布生效,任务开始执行
|
||||
/// </summary>
|
||||
public const string Published = "Published";
|
||||
|
||||
/// <summary>
|
||||
/// 已完成状态 - 所有任务执行完毕
|
||||
/// </summary>
|
||||
public const string Completed = "Completed";
|
||||
|
||||
/// <summary>
|
||||
/// 已撤销状态 - 发布后被撤销
|
||||
/// </summary>
|
||||
public const string Cancelled = "Cancelled";
|
||||
}
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录快照数据
|
||||
/// 用于记录整合记录在特定时刻的完整状态
|
||||
///
|
||||
/// 业务价值:
|
||||
/// 1. 状态追踪:记录整合记录在关键时刻的完整状态
|
||||
/// 2. 变更对比:支持前后状态的对比分析
|
||||
/// 3. 回滚支持:为状态回滚提供数据基础
|
||||
/// 4. 审计完整:提供完整的状态变更审计信息
|
||||
/// </summary>
|
||||
public class IntegrationSnapshot
|
||||
{
|
||||
/// <summary>
|
||||
/// 快照时间
|
||||
/// </summary>
|
||||
public DateTime SnapshotTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 快照类型
|
||||
/// </summary>
|
||||
public string SnapshotType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录状态
|
||||
/// </summary>
|
||||
public string RecordStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态快照
|
||||
/// 记录所有相关任务在快照时刻的状态
|
||||
/// </summary>
|
||||
public List<TaskStatusSnapshot> TaskStatusSnapshots { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配快照
|
||||
/// 记录人员分配在快照时刻的状态
|
||||
/// </summary>
|
||||
public List<PersonnelAssignmentSnapshot> PersonnelAssignmentSnapshots { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配快照
|
||||
/// 记录设备分配在快照时刻的状态
|
||||
/// </summary>
|
||||
public List<EquipmentAssignmentSnapshot> EquipmentAssignmentSnapshots { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 统计信息快照
|
||||
/// </summary>
|
||||
public StatisticsSnapshot StatisticsSnapshot { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 备注信息
|
||||
/// </summary>
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态快照
|
||||
/// </summary>
|
||||
public class TaskStatusSnapshot
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public string Status { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配的人员ID
|
||||
/// </summary>
|
||||
public long? AssignedPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配的人员姓名
|
||||
/// </summary>
|
||||
public string AssignedPersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配的设备ID
|
||||
/// </summary>
|
||||
public long? AssignedEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配的设备名称
|
||||
/// </summary>
|
||||
public string AssignedEquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 快照时间
|
||||
/// </summary>
|
||||
public DateTime SnapshotTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配快照
|
||||
/// </summary>
|
||||
public class PersonnelAssignmentSnapshot
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员姓名
|
||||
/// </summary>
|
||||
public string PersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> AssignedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 工作负载百分比
|
||||
/// </summary>
|
||||
public decimal WorkloadPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 快照时间
|
||||
/// </summary>
|
||||
public DateTime SnapshotTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配快照
|
||||
/// </summary>
|
||||
public class EquipmentAssignmentSnapshot
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long EquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
public string EquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> AssignedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 利用率百分比
|
||||
/// </summary>
|
||||
public decimal UtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 快照时间
|
||||
/// </summary>
|
||||
public DateTime SnapshotTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统计信息快照
|
||||
/// </summary>
|
||||
public class StatisticsSnapshot
|
||||
{
|
||||
/// <summary>
|
||||
/// 总任务数
|
||||
/// </summary>
|
||||
public int TotalTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功任务数
|
||||
/// </summary>
|
||||
public int SuccessTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败任务数
|
||||
/// </summary>
|
||||
public int FailedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功率
|
||||
/// </summary>
|
||||
public decimal SuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员公平性评分
|
||||
/// </summary>
|
||||
public int PersonnelFairnessScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备利用率
|
||||
/// </summary>
|
||||
public decimal EquipmentUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 快照时间
|
||||
/// </summary>
|
||||
public DateTime SnapshotTime { get; set; }
|
||||
}
|
@ -0,0 +1,586 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务变更事件实体
|
||||
/// 记录任务变更事件,用于变更感知和自动触发机制
|
||||
///
|
||||
/// 业务思考:
|
||||
/// 1. 事件驱动架构:基于事件的变更检测和处理机制
|
||||
/// 2. 变更溯源:完整记录变更的前因后果和处理过程
|
||||
/// 3. 批量处理:支持批量变更事件的聚合处理
|
||||
/// 4. 性能优化:通过事件队列机制避免实时处理对系统性能的影响
|
||||
/// </summary>
|
||||
[Table(Name = "sse_task_change_event")]
|
||||
[Index("idx_task_id", "TaskId")] // 任务ID索引
|
||||
[Index("idx_integration_record", "IntegrationRecordId")] // 整合记录索引
|
||||
[Index("idx_event_time", "EventTime")] // 事件时间索引
|
||||
[Index("idx_processing_status", "ProcessingStatus")] // 处理状态索引
|
||||
[Index("idx_tenant_time", "TenantId,EventTime")] // 租户+时间组合索引
|
||||
public class TaskChangeEventEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// 发生变更的任务ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// 冗余存储,提高查询性能
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required]
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 关联的整合记录ID
|
||||
/// 指向受影响的整合记录
|
||||
/// </summary>
|
||||
public long? IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 根版本整合记录ID
|
||||
/// 指向版本链的根节点,用于快速定位整个版本链
|
||||
/// </summary>
|
||||
public long? RootIntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 事件类型
|
||||
/// TaskModified, TaskDeleted, TaskStatusChanged, TaskPriorityChanged,
|
||||
/// TaskTimeChanged, TaskPersonnelChanged, TaskEquipmentChanged, TaskCompleted
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required]
|
||||
public string EventType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更字段名称
|
||||
/// 具体发生变更的字段名,多个字段用逗号分隔
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string ChangedFields { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更前的值(JSON格式)
|
||||
/// 存储变更前的字段值快照
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string BeforeValueJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 变更后的值(JSON格式)
|
||||
/// 存储变更后的字段值快照
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string AfterValueJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 事件发生时间
|
||||
/// 任务实际发生变更的时间
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime EventTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发用户ID
|
||||
/// 执行变更操作的用户ID
|
||||
/// </summary>
|
||||
public long? TriggeredByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发用户名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string TriggeredByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发用户真实姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string TriggeredByRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 事件来源
|
||||
/// Manual-手动操作, System-系统自动, Import-数据导入, API-API调用, Sync-同步操作
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
[Required]
|
||||
public string EventSource { get; set; } = "Manual";
|
||||
|
||||
/// <summary>
|
||||
/// 事件优先级
|
||||
/// 1-9,9为最高优先级,影响处理顺序
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EventPriority { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 影响评估评分
|
||||
/// 0-100分,评估该变更对整合记录的潜在影响
|
||||
/// </summary>
|
||||
public int ImpactAssessmentScore { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 处理状态
|
||||
/// Pending-待处理, Processing-处理中, Completed-已完成, Failed-处理失败, Ignored-已忽略
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
[Required]
|
||||
public string ProcessingStatus { get; set; } = "Pending";
|
||||
|
||||
/// <summary>
|
||||
/// 处理开始时间
|
||||
/// </summary>
|
||||
public DateTime? ProcessingStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理完成时间
|
||||
/// </summary>
|
||||
public DateTime? ProcessingCompletedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理人员用户ID
|
||||
/// 实际处理该事件的用户ID
|
||||
/// </summary>
|
||||
public long? ProcessedByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理人员用户名
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string ProcessedByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 处理结果摘要
|
||||
/// 简述处理结果和采取的行动
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string ProcessingResultSummary { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 处理详情JSON
|
||||
/// 存储详细的处理过程和结果信息
|
||||
/// </summary>
|
||||
[Column(DbType = "json")]
|
||||
public string ProcessingDetailsJson { get; set; } = "{}";
|
||||
|
||||
/// <summary>
|
||||
/// 是否触发了重新分配
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool TriggeredReallocation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 创建的新版本ID
|
||||
/// 如果该事件导致创建了新版本
|
||||
/// </summary>
|
||||
public long? CreatedNewVersionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 事件分组ID
|
||||
/// 用于将相关的多个事件分组处理,如批量修改
|
||||
/// </summary>
|
||||
public long? EventGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 事件分组序号
|
||||
/// 在同一分组内的事件序号
|
||||
/// </summary>
|
||||
public int EventGroupSequence { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要通知
|
||||
/// 标记该事件是否需要发送通知给相关人员
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool RequiresNotification { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 通知状态
|
||||
/// NotSent-未发送, Sent-已发送, Failed-发送失败, NotRequired-无需发送
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
[Required]
|
||||
public string NotificationStatus { get; set; } = "NotSent";
|
||||
|
||||
/// <summary>
|
||||
/// 通知发送时间
|
||||
/// </summary>
|
||||
public DateTime? NotificationSentTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重试次数
|
||||
/// 处理失败后的重试次数
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int RetryCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 最大重试次数
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int MaxRetryCount { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 下次重试时间
|
||||
/// </summary>
|
||||
public DateTime? NextRetryTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// 记录处理过程中的错误信息
|
||||
/// </summary>
|
||||
[Column(StringLength = 1000)]
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 事件标签
|
||||
/// 用于事件分类和筛选,多个标签用逗号分隔
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string EventTags { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 业务备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为测试事件
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool IsTestEvent { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 数据版本
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int DataVersion { get; set; } = 1;
|
||||
|
||||
#region 计算属性
|
||||
|
||||
/// <summary>
|
||||
/// 处理耗时(毫秒)
|
||||
/// </summary>
|
||||
[Navigate(nameof(ProcessingStartTime))]
|
||||
public long ProcessingElapsedMilliseconds
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ProcessingStartTime.HasValue && ProcessingCompletedTime.HasValue)
|
||||
{
|
||||
return (long)(ProcessingCompletedTime.Value - ProcessingStartTime.Value).TotalMilliseconds;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件年龄(自事件发生到现在的分钟数)
|
||||
/// </summary>
|
||||
[Navigate(nameof(EventTime))]
|
||||
public int EventAgeMinutes
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)(DateTime.Now - EventTime).TotalMinutes;
|
||||
}
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否超时
|
||||
/// 判断事件是否长时间未处理
|
||||
/// </summary>
|
||||
[Navigate(nameof(EventTime))]
|
||||
public bool IsOverdue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ProcessingStatus == "Completed" || ProcessingStatus == "Ignored")
|
||||
return false;
|
||||
|
||||
var timeoutMinutes = EventPriority >= 8 ? 30 : EventPriority >= 5 ? 120 : 480; // 高优先级30分钟,中等2小时,低优先级8小时
|
||||
return EventAgeMinutes > timeoutMinutes;
|
||||
}
|
||||
set { } // FreeSql需要set访问器,但这是计算属性,所以提供空实现
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取变更前的值
|
||||
/// 将JSON反序列化为字典
|
||||
/// </summary>
|
||||
public Dictionary<string, object> GetBeforeValues()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(BeforeValueJson) || BeforeValueJson == "{}")
|
||||
return new Dictionary<string, object>();
|
||||
|
||||
return System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(BeforeValueJson)
|
||||
?? new Dictionary<string, object>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取变更后的值
|
||||
/// 将JSON反序列化为字典
|
||||
/// </summary>
|
||||
public Dictionary<string, object> GetAfterValues()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AfterValueJson) || AfterValueJson == "{}")
|
||||
return new Dictionary<string, object>();
|
||||
|
||||
return System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(AfterValueJson)
|
||||
?? new Dictionary<string, object>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置变更前的值
|
||||
/// </summary>
|
||||
public void SetBeforeValues(Dictionary<string, object> values)
|
||||
{
|
||||
BeforeValueJson = System.Text.Json.JsonSerializer.Serialize(values ?? new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置变更后的值
|
||||
/// </summary>
|
||||
public void SetAfterValues(Dictionary<string, object> values)
|
||||
{
|
||||
AfterValueJson = System.Text.Json.JsonSerializer.Serialize(values ?? new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取处理详情
|
||||
/// </summary>
|
||||
public Dictionary<string, object> GetProcessingDetails()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ProcessingDetailsJson) || ProcessingDetailsJson == "{}")
|
||||
return new Dictionary<string, object>();
|
||||
|
||||
return System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(ProcessingDetailsJson)
|
||||
?? new Dictionary<string, object>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置处理详情
|
||||
/// </summary>
|
||||
public void SetProcessingDetails(Dictionary<string, object> details)
|
||||
{
|
||||
ProcessingDetailsJson = System.Text.Json.JsonSerializer.Serialize(details ?? new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始处理事件
|
||||
/// 设置处理开始时间和状态
|
||||
/// </summary>
|
||||
public void StartProcessing(long processedByUserId, string processedByUserName)
|
||||
{
|
||||
ProcessingStatus = "Processing";
|
||||
ProcessingStartTime = DateTime.Now;
|
||||
ProcessedByUserId = processedByUserId;
|
||||
ProcessedByUserName = processedByUserName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 完成处理事件
|
||||
/// 设置处理完成时间和状态
|
||||
/// </summary>
|
||||
public void CompleteProcessing(string resultSummary, bool triggeredReallocation = false, long? createdVersionId = null)
|
||||
{
|
||||
ProcessingStatus = "Completed";
|
||||
ProcessingCompletedTime = DateTime.Now;
|
||||
ProcessingResultSummary = resultSummary;
|
||||
TriggeredReallocation = triggeredReallocation;
|
||||
CreatedNewVersionId = createdVersionId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理失败
|
||||
/// 设置失败状态和错误信息
|
||||
/// </summary>
|
||||
public void FailProcessing(string errorMessage)
|
||||
{
|
||||
ProcessingStatus = "Failed";
|
||||
ProcessingCompletedTime = DateTime.Now;
|
||||
ErrorMessage = errorMessage;
|
||||
RetryCount++;
|
||||
|
||||
// 计算下次重试时间(指数退避)
|
||||
if (RetryCount <= MaxRetryCount)
|
||||
{
|
||||
var delayMinutes = Math.Pow(2, RetryCount) * 5; // 5, 10, 20 分钟
|
||||
NextRetryTime = DateTime.Now.AddMinutes(delayMinutes);
|
||||
ProcessingStatus = "Pending"; // 重置为待处理状态以便重试
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 忽略事件
|
||||
/// 设置忽略状态,不再处理
|
||||
/// </summary>
|
||||
public void IgnoreEvent(string reason)
|
||||
{
|
||||
ProcessingStatus = "Ignored";
|
||||
ProcessingCompletedTime = DateTime.Now;
|
||||
ProcessingResultSummary = $"事件已忽略: {reason}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以重试
|
||||
/// </summary>
|
||||
public bool CanRetry()
|
||||
{
|
||||
return ProcessingStatus == "Pending" &&
|
||||
RetryCount < MaxRetryCount &&
|
||||
(!NextRetryTime.HasValue || NextRetryTime.Value <= DateTime.Now);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算影响评估评分
|
||||
/// 基于变更类型、字段和业务规则计算影响评分
|
||||
/// </summary>
|
||||
public int CalculateImpactScore()
|
||||
{
|
||||
int score = 0;
|
||||
|
||||
// 基于事件类型的基础分数
|
||||
score += EventType switch
|
||||
{
|
||||
"TaskDeleted" => 90,
|
||||
"TaskStatusChanged" => 80,
|
||||
"TaskTimeChanged" => 70,
|
||||
"TaskPriorityChanged" => 60,
|
||||
"TaskPersonnelChanged" => 75,
|
||||
"TaskEquipmentChanged" => 75,
|
||||
"TaskModified" => 50,
|
||||
"TaskCompleted" => 30,
|
||||
_ => 20
|
||||
};
|
||||
|
||||
// 基于变更字段的影响调整
|
||||
if (ChangedFields.Contains("WorkOrderDate")) score += 20;
|
||||
if (ChangedFields.Contains("ShiftId")) score += 15;
|
||||
if (ChangedFields.Contains("Priority")) score += 10;
|
||||
if (ChangedFields.Contains("AssignedPersonnelId")) score += 15;
|
||||
if (ChangedFields.Contains("AssignedEquipmentId")) score += 15;
|
||||
if (ChangedFields.Contains("Status")) score += 25;
|
||||
|
||||
// 基于事件优先级调整
|
||||
score += EventPriority * 2;
|
||||
|
||||
return Math.Min(100, Math.Max(0, score));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件处理状态枚举
|
||||
/// </summary>
|
||||
public static class TaskChangeEventProcessingStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 待处理
|
||||
/// </summary>
|
||||
public const string Pending = "Pending";
|
||||
|
||||
/// <summary>
|
||||
/// 处理中
|
||||
/// </summary>
|
||||
public const string Processing = "Processing";
|
||||
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
public const string Completed = "Completed";
|
||||
|
||||
/// <summary>
|
||||
/// 处理失败
|
||||
/// </summary>
|
||||
public const string Failed = "Failed";
|
||||
|
||||
/// <summary>
|
||||
/// 已忽略
|
||||
/// </summary>
|
||||
public const string Ignored = "Ignored";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件类型枚举
|
||||
/// </summary>
|
||||
public static class TaskChangeEventType
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务修改
|
||||
/// </summary>
|
||||
public const string TaskModified = "TaskModified";
|
||||
|
||||
/// <summary>
|
||||
/// 任务删除
|
||||
/// </summary>
|
||||
public const string TaskDeleted = "TaskDeleted";
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态变更
|
||||
/// </summary>
|
||||
public const string TaskStatusChanged = "TaskStatusChanged";
|
||||
|
||||
/// <summary>
|
||||
/// 任务优先级变更
|
||||
/// </summary>
|
||||
public const string TaskPriorityChanged = "TaskPriorityChanged";
|
||||
|
||||
/// <summary>
|
||||
/// 任务时间变更
|
||||
/// </summary>
|
||||
public const string TaskTimeChanged = "TaskTimeChanged";
|
||||
|
||||
/// <summary>
|
||||
/// 任务人员变更
|
||||
/// </summary>
|
||||
public const string TaskPersonnelChanged = "TaskPersonnelChanged";
|
||||
|
||||
/// <summary>
|
||||
/// 任务设备变更
|
||||
/// </summary>
|
||||
public const string TaskEquipmentChanged = "TaskEquipmentChanged";
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成
|
||||
/// </summary>
|
||||
public const string TaskCompleted = "TaskCompleted";
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 人员资质绑定仓储接口
|
||||
/// </summary>
|
||||
public interface IPersonnelQualificationRepository : IRepositoryBase<PersonnelQualificationEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据工序ID获取符合资质要求的人员
|
||||
/// </summary>
|
||||
/// <param name="processId">工序ID</param>
|
||||
/// <returns>符合资质的人员列表</returns>
|
||||
Task<List<PersonnelQualificationEntity>> GetQualifiedPersonnelByProcessAsync(long processId);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 人员工作限制仓储接口
|
||||
/// </summary>
|
||||
public interface IPersonnelWorkLimitRepository : IRepositoryBase<PersonnelWorkLimitEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 资质仓储接口
|
||||
/// </summary>
|
||||
public interface IQualificationRepository : IRepositoryBase<QualificationEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
|
||||
/// <summary>
|
||||
/// 人员实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "personnel")]
|
||||
public partial class PersonnelEntity : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string PersonnelCode { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 人员姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string PersonnelName { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 部门ID
|
||||
/// </summary>
|
||||
public long? DepartmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string DepartmentName { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 职位
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Position { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 是否激活
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 联系方式
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Contact { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Remarks { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 人员资质列表
|
||||
/// </summary>
|
||||
[Navigate("PersonnelId")]
|
||||
public List<PersonnelQualificationEntity> PersonnelQualifications { get; set; } = new List<PersonnelQualificationEntity>();
|
||||
|
||||
/// <summary>
|
||||
/// 人员工作限制列表
|
||||
/// </summary>
|
||||
[Navigate("PersonnelId")]
|
||||
public List<PersonnelWorkLimitEntity> WorkLimitations { get; set; } = new List<PersonnelWorkLimitEntity>();
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
|
||||
/// <summary>
|
||||
/// 人员资质绑定
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "personnel_qualification")]
|
||||
public partial class PersonnelQualificationEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员姓名
|
||||
/// </summary>
|
||||
public string PersonnelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员工号
|
||||
/// </summary>
|
||||
public string PersonnelCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资质ID
|
||||
/// </summary>
|
||||
public long QualificationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资质等级
|
||||
/// </summary>
|
||||
public string QualificationLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效期(截止日期)
|
||||
/// </summary>
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效期预警天数
|
||||
/// </summary>
|
||||
public int? ExpiryWarningDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 续期日期
|
||||
/// </summary>
|
||||
public DateTime? RenewalDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定状态
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
|
||||
/// <summary>
|
||||
/// 人员工作限制
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "personnel_work_limit")]
|
||||
public partial class PersonnelWorkLimitEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连续工作日限制
|
||||
/// </summary>
|
||||
public int? MaxContinuousWorkDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当周最大排班次数
|
||||
/// </summary>
|
||||
public int? MaxShiftsPerWeek { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 特殊限制规则
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string SpecialRule { get; set; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
|
||||
/// <summary>
|
||||
/// 资质实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "qualification")]
|
||||
public partial class QualificationEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 等级
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string Level { get; set; }
|
||||
}
|
35
NPP.SmartSchedue.Api.Contracts/Domain/Time/CalendarEntity.cs
Normal file
35
NPP.SmartSchedue.Api.Contracts/Domain/Time/CalendarEntity.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 基础日历
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "calendar")]
|
||||
public partial class CalendarEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 日期
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日期类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string DateType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否工作日
|
||||
/// </summary>
|
||||
public bool IsWorkDay { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 特殊日期说明
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string Description { get; set; }
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 员工休假
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "employee_leave")]
|
||||
public partial class EmployeeLeaveEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工ID
|
||||
/// </summary>
|
||||
public long EmployeeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员ID (与PersonnelId对应)
|
||||
/// </summary>
|
||||
public long PersonnelId
|
||||
{
|
||||
get => EmployeeId;
|
||||
set => EmployeeId = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 休假类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string LeaveType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始时间
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束时间
|
||||
/// </summary>
|
||||
public DateTime EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始日期 (与StartTime对应)
|
||||
/// </summary>
|
||||
public DateTime StartDate
|
||||
{
|
||||
get => StartTime.Date;
|
||||
set => StartTime = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束日期 (与EndTime对应)
|
||||
/// </summary>
|
||||
public DateTime EndDate
|
||||
{
|
||||
get => EndTime.Date;
|
||||
set => EndTime = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 休假状态
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请原因
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审批人ID
|
||||
/// </summary>
|
||||
public long? ApproverId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审批时间
|
||||
/// </summary>
|
||||
public DateTime? ApprovalTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审批意见
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string ApprovalComment { get; set; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 基础日历仓储接口
|
||||
/// </summary>
|
||||
public interface ICalendarRepository : IRepositoryBase<CalendarEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 员工休假仓储接口
|
||||
/// </summary>
|
||||
public interface IEmployeeLeaveRepository : IRepositoryBase<EmployeeLeaveEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 人员班次分配仓储接口
|
||||
/// </summary>
|
||||
public interface IPersonnelShiftAssignmentRepository : IRepositoryBase<PersonnelShiftAssignmentEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 生产班次仓储接口
|
||||
/// </summary>
|
||||
public interface IShiftRepository : IRepositoryBase<ShiftEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则关联仓储接口
|
||||
/// </summary>
|
||||
public interface IShiftRuleMappingRepository : IRepositoryBase<ShiftRuleMappingEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据班次ID获取有效的班次规则列表
|
||||
/// 深度业务思考:通过映射表关联,获取班次对应的所有有效规则
|
||||
/// </summary>
|
||||
/// <param name="shiftId">班次ID</param>
|
||||
/// <param name="targetDate">目标日期(用于生效时间判断)</param>
|
||||
/// <returns>有效的班次规则列表</returns>
|
||||
Task<List<ShiftRuleEntity>> GetEffectiveShiftRulesAsync(long shiftId, DateTime? targetDate = null);
|
||||
|
||||
/// <summary>
|
||||
/// 批量获取多个班次的规则映射
|
||||
/// 深度业务思考:批量查询优化,避免N+1查询问题
|
||||
/// </summary>
|
||||
/// <param name="shiftIds">班次ID列表</param>
|
||||
/// <param name="targetDate">目标日期(用于生效时间判断)</param>
|
||||
/// <returns>班次ID到规则列表的映射</returns>
|
||||
Task<Dictionary<long, List<ShiftRuleEntity>>> GetBatchShiftRulesAsync(List<long> shiftIds, DateTime? targetDate = null);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则仓储接口
|
||||
/// </summary>
|
||||
public interface IShiftRuleRepository : IRepositoryBase<ShiftRuleEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取适用于特定人员、日期和班次的排班规则
|
||||
/// </summary>
|
||||
/// <param name="personnelId">人员ID</param>
|
||||
/// <param name="targetDate">目标日期</param>
|
||||
/// <param name="shiftId">班次ID(可选)</param>
|
||||
/// <returns>适用的排班规则列表</returns>
|
||||
Task<List<ShiftRuleEntity>> GetApplicableRulesAsync(long personnelId, DateTime targetDate, long? shiftId);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 人员班次分配
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "personnel_shift_assignment")]
|
||||
public partial class PersonnelShiftAssignmentEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次ID
|
||||
/// </summary>
|
||||
public long ShiftId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配日期
|
||||
/// </summary>
|
||||
public DateTime AssignmentDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配类型 (指定/自动)
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string AssignmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配原因
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string AssignmentReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配状态
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否违反规则
|
||||
/// </summary>
|
||||
public bool IsRuleViolation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 违反规则描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string ViolationDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 年度累计班次数
|
||||
/// </summary>
|
||||
public int YearlyShiftCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 周累计班次数
|
||||
/// </summary>
|
||||
public int WeeklyShiftCount { get; set; } = 0;
|
||||
}
|
57
NPP.SmartSchedue.Api.Contracts/Domain/Time/ShiftEntity.cs
Normal file
57
NPP.SmartSchedue.Api.Contracts/Domain/Time/ShiftEntity.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 生产班次
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "shift")]
|
||||
[Index("ix_shift_shiftnumber_enabled", nameof(ShiftNumber))]
|
||||
[Index("ix_shift_starttime_endtime", nameof(StartTime))]
|
||||
public partial class ShiftEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 班次名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Name { get; set; }
|
||||
|
||||
public int ShiftNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次开始时间
|
||||
/// </summary>
|
||||
public TimeSpan StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次结束时间
|
||||
/// </summary>
|
||||
public TimeSpan EndTime { get; set; }
|
||||
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 班次描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次后强制休息天数 (默认值,可被规则覆盖)
|
||||
/// </summary>
|
||||
public int RestDaysAfterShift { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 是否允许连续排班 (默认值,可被规则覆盖)
|
||||
/// </summary>
|
||||
public bool AllowConsecutive { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 班次优先级权重
|
||||
/// </summary>
|
||||
public int PriorityWeight { get; set; } = 1;
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则配置
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "shift_rule")]
|
||||
[Index("ix_shiftrule_type_enabled", nameof(RuleType))]
|
||||
[Index("ix_shiftrule_effective_time", nameof(EffectiveStartTime))]
|
||||
public partial class ShiftRuleEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string RuleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则类型
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string RuleType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 规则参数 (JSON格式)
|
||||
/// </summary>
|
||||
[Column(StringLength = 2000)]
|
||||
public string RuleParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认优先级
|
||||
/// </summary>
|
||||
public int DefaultPriority { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 规则生效开始时间
|
||||
/// </summary>
|
||||
public DateTime? EffectiveStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则生效结束时间
|
||||
/// </summary>
|
||||
public DateTime? EffectiveEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则版本号
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string Version { get; set; } = "1.0";
|
||||
|
||||
/// <summary>
|
||||
/// 规则映射集合
|
||||
/// </summary>
|
||||
[Navigate(nameof(ShiftRuleMappingEntity.RuleId))]
|
||||
public virtual List<ShiftRuleMappingEntity> ShiftRuleMappings { get; set; }
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则关联
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "shift_rule_mapping")]
|
||||
public partial class ShiftRuleMappingEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 班次ID
|
||||
/// </summary>
|
||||
public long ShiftId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则ID
|
||||
/// </summary>
|
||||
public long RuleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则覆盖参数 (JSON格式,覆盖规则默认参数)
|
||||
/// </summary>
|
||||
[Column(StringLength = 1500)]
|
||||
public string OverrideParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用该规则
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 规则执行优先级 (数字越小优先级越高)
|
||||
/// </summary>
|
||||
public int ExecutionPriority { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 规则生效开始时间 (覆盖规则默认时间)
|
||||
/// </summary>
|
||||
public DateTime? EffectiveStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则生效结束时间 (覆盖规则默认时间)
|
||||
/// </summary>
|
||||
public DateTime? EffectiveEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 映射描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 300)]
|
||||
public string MappingDescription { get; set; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 工序组关联关系仓储接口
|
||||
/// </summary>
|
||||
public interface IProcessGroupRelationRepository : IRepositoryBase<ProcessGroupRelationEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 工序组仓储接口
|
||||
/// </summary>
|
||||
public interface IProcessGroupRepository : IRepositoryBase<ProcessGroupEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// 工序仓储接口
|
||||
/// </summary>
|
||||
public interface IProcessRepository : IRepositoryBase<ProcessEntity>
|
||||
{
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工作任务FL人员关联仓储接口
|
||||
/// </summary>
|
||||
public interface IWorkOrderFLPersonnelRepository : IRepositoryBase<WorkOrderFLPersonnelEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据工作任务ID获取FL人员列表
|
||||
/// </summary>
|
||||
/// <param name="workOrderId">工作任务ID</param>
|
||||
/// <returns>FL人员列表</returns>
|
||||
Task<List<WorkOrderFLPersonnelEntity>> GetByWorkOrderIdAsync(long workOrderId);
|
||||
|
||||
/// <summary>
|
||||
/// 根据FL人员ID获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="flPersonnelId">FL人员ID</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderFLPersonnelEntity>> GetByPersonnelIdAsync(long personnelId);
|
||||
|
||||
/// <summary>
|
||||
/// 批量添加工作任务FL人员关联
|
||||
/// </summary>
|
||||
/// <param name="workOrderId">工作任务ID</param>
|
||||
/// <param name="flPersonnelIds">FL人员ID列表</param>
|
||||
/// <param name="flPersonnelNames">FL人员姓名列表</param>
|
||||
/// <returns>添加结果</returns>
|
||||
Task<bool> BatchAddAsync(long workOrderId, List<long> flPersonnelIds, List<string> flPersonnelNames);
|
||||
|
||||
/// <summary>
|
||||
/// 根据工作任务ID删除所有FL人员关联
|
||||
/// </summary>
|
||||
/// <param name="workOrderId">工作任务ID</param>
|
||||
/// <returns>删除结果</returns>
|
||||
Task<bool> DeleteByWorkOrderIdAsync(long workOrderId);
|
||||
|
||||
/// <summary>
|
||||
/// 更新工作任务的FL人员关联
|
||||
/// </summary>
|
||||
/// <param name="workOrderId">工作任务ID</param>
|
||||
/// <param name="flPersonnelIds">新的FL人员ID列表</param>
|
||||
/// <param name="flPersonnelNames">新的FL人员姓名列表</param>
|
||||
/// <returns>更新结果</returns>
|
||||
Task<bool> UpdateByWorkOrderIdAsync(long workOrderId, List<long> flPersonnelIds, List<string> flPersonnelNames);
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工作任务仓储接口
|
||||
/// </summary>
|
||||
public interface IWorkOrderRepository : IRepositoryBase<WorkOrderEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据日期获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="date">日期</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderEntity>> GetByDateAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 根据人员ID和日期范围获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="personnelId">人员ID</param>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderEntity>> GetByPersonnelAndDateRangeAsync(long personnelId, DateTime startDate, DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 根据状态获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="status">任务状态</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderEntity>> GetByStatusAsync(WorkOrderStatusEnum status);
|
||||
|
||||
/// <summary>
|
||||
/// 根据班次ID获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="shiftId">班次ID</param>
|
||||
/// <param name="date">日期</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderEntity>> GetByShiftAndDateAsync(long shiftId, DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 根据工序ID获取工作任务列表
|
||||
/// </summary>
|
||||
/// <param name="processId">工序ID</param>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>工作任务列表</returns>
|
||||
Task<List<WorkOrderEntity>> GetByProcessAndDateRangeAsync(long processId, DateTime startDate, DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 检查任务代码是否存在
|
||||
/// </summary>
|
||||
/// <param name="workOrderCode">任务代码</param>
|
||||
/// <param name="excludeId">排除的ID</param>
|
||||
/// <returns>是否存在</returns>
|
||||
Task<bool> ExistsWorkOrderCodeAsync(string workOrderCode, long? excludeId = null);
|
||||
|
||||
/// <summary>
|
||||
/// 生成任务代码
|
||||
/// </summary>
|
||||
/// <param name="projectNumber">项目号</param>
|
||||
/// <param name="shiftCode">班次代码</param>
|
||||
/// <param name="processCode">工序代码</param>
|
||||
/// <returns>任务代码</returns>
|
||||
string GenerateWorkOrderCode(string projectNumber, string shiftCode, string processCode);
|
||||
|
||||
/// <summary>
|
||||
/// 获取人员在指定日期范围内的任务数量
|
||||
/// </summary>
|
||||
/// <param name="personnelId">人员ID</param>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>任务数量</returns>
|
||||
Task<int> GetPersonnelTaskCountByDateRangeAsync(long personnelId, DateTime startDate, DateTime endDate);
|
||||
}
|
74
NPP.SmartSchedue.Api.Contracts/Domain/Work/ProcessEntity.cs
Normal file
74
NPP.SmartSchedue.Api.Contracts/Domain/Work/ProcessEntity.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工序实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "process")]
|
||||
public partial class ProcessEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 工序编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string ProcessCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string ProcessName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序分类
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string ProcessCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员资质要求
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string QualificationRequirements { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string? EquipmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 理论任务时长(小时)
|
||||
/// </summary>
|
||||
public decimal TheoreticalDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 工序优先级
|
||||
/// </summary>
|
||||
public int Priority { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 预估持续时间
|
||||
/// </summary>
|
||||
public TimeSpan? EstimatedDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型ID
|
||||
/// </summary>
|
||||
public long? EquipmentTypeId { get; set; }
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工序组实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "process_group")]
|
||||
public partial class ProcessGroupEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 工序组名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目类别
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string ProjectCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序组描述
|
||||
/// </summary>
|
||||
[Column(StringLength = 500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 工序组优先级
|
||||
/// </summary>
|
||||
public int Priority { get; set; } = 1;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工序组关联关系实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "process_group_relation")]
|
||||
public partial class ProcessGroupRelationEntity : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 工序组ID
|
||||
/// </summary>
|
||||
public long ProcessGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序ID
|
||||
/// </summary>
|
||||
public long ProcessId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联类型 (A=>B, A=>B=>C)
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string RelationType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 前置工序ID
|
||||
/// </summary>
|
||||
public long? PredecessorProcessId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 后置工序ID
|
||||
/// </summary>
|
||||
public long? SuccessorProcessId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联顺序
|
||||
/// </summary>
|
||||
public int RelationOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
}
|
275
NPP.SmartSchedue.Api.Contracts/Domain/Work/WorkOrderEntity.cs
Normal file
275
NPP.SmartSchedue.Api.Contracts/Domain/Work/WorkOrderEntity.cs
Normal file
@ -0,0 +1,275 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工作任务实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "work_order")]
|
||||
public partial class WorkOrderEntity : EntityTenant
|
||||
{
|
||||
#region 基础信息
|
||||
|
||||
/// <summary>
|
||||
/// 项目号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required(ErrorMessage = "项目号不能为空")]
|
||||
public string ProjectNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目类别
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
[Required(ErrorMessage = "项目类别不能为空")]
|
||||
public string ProjectCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次ID
|
||||
/// </summary>
|
||||
public long? ShiftId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次代码
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string ShiftCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string ShiftName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "工序不能为空")]
|
||||
public long ProcessId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序代码
|
||||
/// </summary>
|
||||
[Column(StringLength = 20)]
|
||||
public string ProcessCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string ProcessName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序分类
|
||||
/// </summary>
|
||||
public string ProcessCategory { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 任务信息
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码(项目号_班次code_工序code)
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string WorkOrderCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 批号
|
||||
/// </summary>
|
||||
[Column(StringLength = 50)]
|
||||
public string BatchNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务日期
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "任务日期不能为空")]
|
||||
public DateTime WorkOrderDate { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public int Status { get; set; } = (int)WorkOrderStatusEnum.PendingSubmit;
|
||||
|
||||
/// <summary>
|
||||
/// 优先级(1-10,数字越大优先级越高)
|
||||
/// </summary>
|
||||
public int Priority { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 预计工时(小时)
|
||||
/// </summary>
|
||||
[Column(Precision = 10, Scale = 2)]
|
||||
public decimal? EstimatedHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 紧急程度(1-10,数字越大越紧急)
|
||||
/// </summary>
|
||||
public int Urgency { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 任务复杂度(别名,使用Priority表示)
|
||||
/// </summary>
|
||||
[Column(MapType = typeof(int), IsIgnore = true)]
|
||||
public int Complexity
|
||||
{
|
||||
get => Priority;
|
||||
set => Priority = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权重系数(用于排序和优先级计算)
|
||||
/// </summary>
|
||||
[Column(Precision = 10, Scale = 4)]
|
||||
public double WeightFactor { get; set; } = 1.0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 人员和设备
|
||||
|
||||
/// <summary>
|
||||
/// 任务实施人员ID
|
||||
/// </summary>
|
||||
public long? AssignedPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务实施人员姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string AssignedPersonnelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务设备ID
|
||||
/// </summary>
|
||||
public long? AssignedEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务设备名称
|
||||
/// </summary>
|
||||
[Column(StringLength = 200)]
|
||||
public string AssignedEquipmentName { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 时间信息
|
||||
|
||||
/// <summary>
|
||||
/// 任务实际开始时间
|
||||
/// </summary>
|
||||
public DateTime? ActualStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务实际结束时间
|
||||
/// </summary>
|
||||
public DateTime? ActualEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际完成工时(小时)
|
||||
/// </summary>
|
||||
[Column(Precision = 10, Scale = 2)]
|
||||
public decimal? ActualWorkHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际完成工时(别名,与 ActualWorkHours 相同)
|
||||
/// </summary>
|
||||
[Column(MapType = typeof(decimal?), IsIgnore = true)]
|
||||
public decimal? ActualCompletedHours
|
||||
{
|
||||
get => ActualWorkHours;
|
||||
set => ActualWorkHours = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务分配时间
|
||||
/// </summary>
|
||||
public DateTime? AssignedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后修改时间
|
||||
/// </summary>
|
||||
public DateTime? LastModifiedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注信息
|
||||
/// </summary>
|
||||
[Column(StringLength = 1000)]
|
||||
public string Remarks { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 计划开始时间
|
||||
/// </summary>
|
||||
public DateTime PlannedStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计划结束时间
|
||||
/// </summary>
|
||||
public DateTime PlannedEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码/编号
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 紧急程度级别(使用Urgency的别名)
|
||||
/// </summary>
|
||||
[Column(MapType = typeof(int), IsIgnore = true)]
|
||||
public int UrgencyLevel
|
||||
{
|
||||
get => Urgency;
|
||||
set => Urgency = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复杂度级别(使用Priority的别名)
|
||||
/// </summary>
|
||||
[Column(MapType = typeof(int), IsIgnore = true)]
|
||||
public int ComplexityLevel
|
||||
{
|
||||
get => Priority;
|
||||
set => Priority = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
public long? IntegrationRecordId { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 导航属性
|
||||
|
||||
/// <summary>
|
||||
/// 工序实体
|
||||
/// </summary>
|
||||
[Navigate("ProcessId")]
|
||||
public ProcessEntity? ProcessEntity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次实体
|
||||
/// </summary>
|
||||
[Navigate("ShiftId")]
|
||||
public ShiftEntity? ShiftEntity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FL人员关联列表
|
||||
/// </summary>
|
||||
[Navigate("WorkOrderId")]
|
||||
public List<WorkOrderFLPersonnelEntity> WorkOrderFLPersonnels { get; set; } = new List<WorkOrderFLPersonnelEntity>();
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using FreeSql.DataAnnotations;
|
||||
using ZhonTai.Admin.Core.Entities;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Consts;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
/// <summary>
|
||||
/// 工作任务FL人员关联实体
|
||||
/// </summary>
|
||||
[Table(Name = DbConsts.TableNamePrefix + "work_order_fl_personnel")]
|
||||
public partial class WorkOrderFLPersonnelEntity : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 工作任务ID
|
||||
/// </summary>
|
||||
public long WorkOrderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FL人员ID
|
||||
/// </summary>
|
||||
public long FLPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FL人员姓名
|
||||
/// </summary>
|
||||
[Column(StringLength = 100)]
|
||||
public string FLPersonnelName { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 人员实体
|
||||
/// </summary>
|
||||
[Navigate("PersonnelId")]
|
||||
public PersonnelEntity? PersonnelEntity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public new DateTime CreatedTime { get; set; } = DateTime.Now;
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Description>NPP.SmartSchedue接口契约库</Description>
|
||||
<Version>1.0.0</Version>
|
||||
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>xiaoxue</Authors>
|
||||
<Company>zhontai</Company>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://admin.zhontai.net</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/zhontai/Admin.Core</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>ZhonTai Admin Api Contracts;</PackageTags>
|
||||
<NoWarn>1701;1702;1591;8632;SYSLIB0020;CS8002;NU1902;NU1903;NU1904;</NoWarn>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>false</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ZhonTai.Admin.Core" Version="9.1.1">
|
||||
<IsBuild>true</IsBuild>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ZhonTai.Admin.Contracts" Version="9.1.1">
|
||||
<IsBuild>true</IsBuild>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Domain\"/>
|
||||
<Folder Include="Domain\Schedule\" />
|
||||
<Folder Include="Services\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="AfterTargetsBuild" AfterTargets="Build">
|
||||
<ItemGroup>
|
||||
<PackageReferenceXmlFiles Condition="'%(PackageReference.IsBuild)' == 'true'" Include="$(NugetPackageRoot)\$([MSBuild]::Escape('%(PackageReference.Identity)').ToLower())\%(PackageReference.Version)\**\*.xml"/>
|
||||
<PackageReferenceJsonFiles Condition="'%(PackageReference.IsBuild)' == 'true'" Include="$(NugetPackageRoot)\$([MSBuild]::Escape('%(PackageReference.Identity)').ToLower())\%(PackageReference.Version)\**\*.json"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Copy Condition="'%(PackageReferenceXmlFiles.Identity)' != ''" SourceFiles="@(PackageReferenceXmlFiles)" DestinationFolder="./../NPP.SmartSchedue.Host/$(OutDir)"/>
|
||||
<Copy Condition="'%(PackageReferenceJsonFiles.Identity)' != ''" SourceFiles="@(PackageReferenceJsonFiles)" DestinationFolder="./../NPP.SmartSchedue.Host/$(OutDir)Resources"/>
|
||||
<Copy Condition="'%(PackageReferenceXmlFiles.Identity)' != ''" SourceFiles="@(PackageReferenceXmlFiles)" DestinationFolder="./../NPP.SmartSchedue.Tests/$(OutDir)"/>
|
||||
<Copy Condition="'%(PackageReferenceJsonFiles.Identity)' != ''" SourceFiles="@(PackageReferenceJsonFiles)" DestinationFolder="./../NPP.SmartSchedue.Tests/$(OutDir)Resources"/>
|
||||
</Target>
|
||||
</Project>
|
@ -0,0 +1,14 @@
|
||||
using FreeSql;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
|
||||
using ZhonTai.Admin.Core.Repositories;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Repositories.Equipment
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备仓储接口
|
||||
/// 职责:定义设备实体的数据访问接口
|
||||
/// </summary>
|
||||
public interface IEquipmentRepository : IRepositoryBase<EquipmentEntity>
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 设备列表输出
|
||||
/// </summary>
|
||||
public class EquipmentListOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备型号
|
||||
/// </summary>
|
||||
public string Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部编号
|
||||
/// </summary>
|
||||
public string InternalNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 房间号
|
||||
/// </summary>
|
||||
public string RoomNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备负责人姓名
|
||||
/// </summary>
|
||||
public string ResponsiblePersonName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备位置
|
||||
/// </summary>
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后维护日期
|
||||
/// </summary>
|
||||
public DateTime? LastMaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次维护日期
|
||||
/// </summary>
|
||||
public DateTime? NextMaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后校验日期
|
||||
/// </summary>
|
||||
public DateTime? LastCalibrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次校验日期
|
||||
/// </summary>
|
||||
public DateTime? NextCalibrationDate { get; set; }
|
||||
|
||||
public long ProcessId { get; set; }
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 按设备类型统计输出模型
|
||||
/// 包含设备数量、状态分布等核心统计信息
|
||||
/// </summary>
|
||||
public class EquipmentTypeStatisticsOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备类型(Production, Testing, Laboratory, Office, Other)
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型显示名称
|
||||
/// </summary>
|
||||
public string EquipmentTypeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 总设备数量
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按状态分组的设备数量统计
|
||||
/// 业务深度思考:涵盖设备全生命周期状态,支持设备管理决策
|
||||
/// </summary>
|
||||
public EquipmentStatusDistribution StatusDistribution { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 平均设备使用年限(年)
|
||||
/// </summary>
|
||||
public decimal AverageServiceYears { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备价值统计(总价值、平均单价)
|
||||
/// </summary>
|
||||
public EquipmentValueStatistics ValueStatistics { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 最近维护信息汇总
|
||||
/// </summary>
|
||||
public MaintenanceSummary MaintenanceSummary { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态分布统计
|
||||
/// 深度业务场景:支持设备健康度评估和维护规划
|
||||
/// </summary>
|
||||
public class EquipmentStatusDistribution
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常状态设备数量
|
||||
/// </summary>
|
||||
public int NormalCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护中设备数量
|
||||
/// </summary>
|
||||
public int MaintenanceCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验中设备数量
|
||||
/// </summary>
|
||||
public int CalibrationCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障设备数量
|
||||
/// </summary>
|
||||
public int FaultCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 报废设备数量
|
||||
/// </summary>
|
||||
public int ScrapCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 停用设备数量
|
||||
/// </summary>
|
||||
public int InactiveCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备健康度百分比(正常设备占比)
|
||||
/// </summary>
|
||||
public decimal HealthPercentage => TotalActiveCount > 0 ?
|
||||
(decimal)NormalCount / TotalActiveCount * 100 : 0;
|
||||
|
||||
/// <summary>
|
||||
/// 活跃设备总数(排除报废和停用)
|
||||
/// </summary>
|
||||
public int TotalActiveCount => NormalCount + MaintenanceCount + CalibrationCount + FaultCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备价值统计
|
||||
/// 业务深度思考:支持资产管理和投资回报分析
|
||||
/// </summary>
|
||||
public class EquipmentValueStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// 总资产价值
|
||||
/// </summary>
|
||||
public decimal TotalValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均单台价值
|
||||
/// </summary>
|
||||
public decimal AverageValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最高单台价值
|
||||
/// </summary>
|
||||
public decimal MaxValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最低单台价值
|
||||
/// </summary>
|
||||
public decimal MinValue { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 维护信息汇总
|
||||
/// 深度业务场景:支持维护成本分析和维护策略优化
|
||||
/// </summary>
|
||||
public class MaintenanceSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 最近30天内维护次数
|
||||
/// </summary>
|
||||
public int RecentMaintenanceCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均维护间隔天数
|
||||
/// </summary>
|
||||
public decimal AverageMaintenanceInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下次预计维护日期
|
||||
/// </summary>
|
||||
public DateTime? NextMaintenanceDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护成本趋势(相比上期增长百分比)
|
||||
/// </summary>
|
||||
public decimal MaintenanceCostTrend { get; set; }
|
||||
}
|
@ -0,0 +1,322 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型任务分配统计输出模型
|
||||
/// 深度业务场景:支持工艺流程分析、设备负荷均衡评估和生产计划优化
|
||||
/// </summary>
|
||||
public class EquipmentTypeTaskAllocationOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型显示名称
|
||||
/// </summary>
|
||||
public string EquipmentTypeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间段
|
||||
/// </summary>
|
||||
public DateTime StatisticsPeriodStart { get; set; }
|
||||
public DateTime StatisticsPeriodEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务分配汇总统计
|
||||
/// 深度业务思考:全面反映该设备类型的工作负荷情况
|
||||
/// </summary>
|
||||
public TaskAllocationSummary AllocationSummary { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 按优先级分组的任务分配统计
|
||||
/// 业务深度逻辑:支持紧急任务和常规任务的资源分配决策
|
||||
/// </summary>
|
||||
public List<TaskPriorityAllocation> PriorityAllocations { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 按工序类型分组的任务分配统计
|
||||
/// 深度业务场景:分析该设备类型在不同工序中的使用情况
|
||||
/// </summary>
|
||||
public List<ProcessTypeAllocation> ProcessAllocations { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 按时间段的任务分配分布
|
||||
/// 支持24小时工作负荷分析和班次安排优化
|
||||
/// </summary>
|
||||
public List<TimeSlotAllocation> TimeSlotAllocations { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备负荷均衡分析
|
||||
/// 深度业务思考:评估设备间的工作负荷分布是否合理
|
||||
/// </summary>
|
||||
public LoadBalanceAnalysis LoadBalanceAnalysis { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成质量指标
|
||||
/// 业务深度场景:评估该设备类型在任务执行中的表现
|
||||
/// </summary>
|
||||
public TaskCompletionQuality CompletionQuality { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务分配汇总统计
|
||||
/// </summary>
|
||||
public class TaskAllocationSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 总任务数量
|
||||
/// </summary>
|
||||
public int TotalTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已完成任务数量
|
||||
/// </summary>
|
||||
public int CompletedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进行中任务数量
|
||||
/// </summary>
|
||||
public int InProgressTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 待分配任务数量
|
||||
/// </summary>
|
||||
public int PendingTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已取消任务数量
|
||||
/// </summary>
|
||||
public int CancelledTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总预估工时(小时)
|
||||
/// </summary>
|
||||
public decimal TotalEstimatedHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总实际工时(小时)
|
||||
/// </summary>
|
||||
public decimal TotalActualHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工时准确率(实际工时与预估工时的比值)
|
||||
/// 深度业务逻辑:评估工时预估的准确性,支持后续预估优化
|
||||
/// </summary>
|
||||
public decimal TimeAccuracyRate => TotalEstimatedHours > 0 ?
|
||||
TotalActualHours / TotalEstimatedHours * 100 : 0;
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成率(百分比)
|
||||
/// </summary>
|
||||
public decimal CompletionRate => TotalTaskCount > 0 ?
|
||||
(decimal)CompletedTaskCount / TotalTaskCount * 100 : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按优先级的任务分配统计
|
||||
/// 深度业务思考:分析不同优先级任务的分配和完成情况
|
||||
/// </summary>
|
||||
public class TaskPriorityAllocation
|
||||
{
|
||||
/// <summary>
|
||||
/// 优先级等级
|
||||
/// </summary>
|
||||
public int PriorityLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 优先级名称(紧急、高、中、低)
|
||||
/// </summary>
|
||||
public string PriorityName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 该优先级任务数量
|
||||
/// </summary>
|
||||
public int TaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该优先级任务占比(百分比)
|
||||
/// </summary>
|
||||
public decimal TaskPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均完成时间(小时)
|
||||
/// </summary>
|
||||
public decimal AverageCompletionTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按时完成率(百分比)
|
||||
/// 深度业务指标:评估高优先级任务的及时完成情况
|
||||
/// </summary>
|
||||
public decimal OnTimeCompletionRate { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按工序类型的任务分配统计
|
||||
/// </summary>
|
||||
public class ProcessTypeAllocation
|
||||
{
|
||||
/// <summary>
|
||||
/// 工序类型
|
||||
/// </summary>
|
||||
public string ProcessType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 工序名称
|
||||
/// </summary>
|
||||
public string ProcessName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 该工序类型的任务数量
|
||||
/// </summary>
|
||||
public int TaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该工序类型任务占比
|
||||
/// </summary>
|
||||
public decimal TaskPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该工序的平均耗时(小时)
|
||||
/// </summary>
|
||||
public decimal AverageDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该工序的标准耗时(小时)
|
||||
/// </summary>
|
||||
public decimal StandardDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序效率指标(实际耗时与标准耗时的比值)
|
||||
/// 深度业务分析:评估工序执行效率,识别改进机会
|
||||
/// </summary>
|
||||
public decimal EfficiencyRatio => StandardDuration > 0 ?
|
||||
StandardDuration / AverageDuration * 100 : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时间段任务分配分布
|
||||
/// 深度业务场景:支持24小时生产排程和班次优化决策
|
||||
/// </summary>
|
||||
public class TimeSlotAllocation
|
||||
{
|
||||
/// <summary>
|
||||
/// 时间段(小时,0-23)
|
||||
/// </summary>
|
||||
public int TimeSlot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该时间段的任务数量
|
||||
/// </summary>
|
||||
public int TaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该时间段的设备使用率
|
||||
/// </summary>
|
||||
public decimal UtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该时间段的平均任务持续时间
|
||||
/// </summary>
|
||||
public decimal AverageTaskDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该时间段对应的班次信息
|
||||
/// </summary>
|
||||
public string ShiftName { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 负荷均衡分析
|
||||
/// 深度业务思考:评估设备类型内各设备间的工作分配是否均衡
|
||||
/// </summary>
|
||||
public class LoadBalanceAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 最高负荷设备的工作量
|
||||
/// </summary>
|
||||
public decimal MaxWorkload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最低负荷设备的工作量
|
||||
/// </summary>
|
||||
public decimal MinWorkload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均工作量
|
||||
/// </summary>
|
||||
public decimal AverageWorkload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 负荷均衡系数(0-1,越接近1越均衡)
|
||||
/// 计算逻辑:1 - (最大工作量 - 最小工作量) / 平均工作量
|
||||
/// </summary>
|
||||
public decimal BalanceCoefficient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作量标准差
|
||||
/// 深度统计分析:衡量设备间工作量分布的离散程度
|
||||
/// </summary>
|
||||
public decimal WorkloadStandardDeviation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 负荷均衡评级(Excellent, Good, Average, Poor)
|
||||
/// </summary>
|
||||
public string BalanceRating { get; set; } = "Average";
|
||||
|
||||
/// <summary>
|
||||
/// 均衡优化建议
|
||||
/// </summary>
|
||||
public List<string> OptimizationSuggestions { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成质量指标
|
||||
/// 深度业务评估:从多维度评价设备类型的任务执行质量
|
||||
/// </summary>
|
||||
public class TaskCompletionQuality
|
||||
{
|
||||
/// <summary>
|
||||
/// 准时完成率(百分比)
|
||||
/// </summary>
|
||||
public decimal OnTimeCompletionRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 质量合格率(百分比)
|
||||
/// </summary>
|
||||
public decimal QualityPassRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返工率(百分比)
|
||||
/// </summary>
|
||||
public decimal ReworkRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均延期天数
|
||||
/// </summary>
|
||||
public decimal AverageDelayDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 客户满意度评分(1-5分)
|
||||
/// </summary>
|
||||
public decimal CustomerSatisfactionScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 综合质量得分(0-100分)
|
||||
/// 深度业务算法:综合考虑准时性、质量、客户满意度等因素
|
||||
/// </summary>
|
||||
public decimal OverallQualityScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 质量等级(Excellent, Good, Average, Poor)
|
||||
/// </summary>
|
||||
public string QualityGrade { get; set; } = "Average";
|
||||
|
||||
/// <summary>
|
||||
/// 质量改进建议
|
||||
/// </summary>
|
||||
public List<string> ImprovementRecommendations { get; set; } = new();
|
||||
}
|
@ -0,0 +1,511 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型趋势分析输出模型
|
||||
/// 深度业务场景:支持长期设备投资规划、维护策略制定和产能预测
|
||||
/// </summary>
|
||||
public class EquipmentTypeTrendOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型显示名称
|
||||
/// </summary>
|
||||
public string EquipmentTypeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 趋势分析时间段
|
||||
/// </summary>
|
||||
public DateTime TrendPeriodStart { get; set; }
|
||||
public DateTime TrendPeriodEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分组周期类型(Day, Week, Month)
|
||||
/// </summary>
|
||||
public string GroupByPeriod { get; set; } = "Day";
|
||||
|
||||
/// <summary>
|
||||
/// 时间序列趋势数据点
|
||||
/// 深度业务分析:按时间周期组织的关键指标变化趋势
|
||||
/// </summary>
|
||||
public List<TrendDataPoint> TrendDataPoints { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 趋势分析汇总
|
||||
/// </summary>
|
||||
public TrendAnalysisSummary AnalysisSummary { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 预测分析结果
|
||||
/// 深度业务智能:基于历史数据的未来趋势预测
|
||||
/// </summary>
|
||||
public PredictionAnalysis PredictionAnalysis { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 异常检测结果
|
||||
/// 业务深度思考:识别异常波动和潜在风险点
|
||||
/// </summary>
|
||||
public List<AnomalyDetection> AnomalyDetections { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 季节性分析
|
||||
/// 支持识别生产淡旺季对设备使用的影响
|
||||
/// </summary>
|
||||
public SeasonalityAnalysis SeasonalityAnalysis { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 趋势数据点
|
||||
/// 时间序列中的单个数据点,包含关键业务指标
|
||||
/// </summary>
|
||||
public class TrendDataPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据点时间
|
||||
/// </summary>
|
||||
public DateTime DataPointTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间段标识(如:2024-01-01 或 2024-W01)
|
||||
/// </summary>
|
||||
public string PeriodLabel { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备使用率(百分比)
|
||||
/// </summary>
|
||||
public decimal UtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成数量
|
||||
/// </summary>
|
||||
public int CompletedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均任务持续时间(小时)
|
||||
/// </summary>
|
||||
public decimal AverageTaskDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备可用率(百分比)
|
||||
/// 深度业务指标:考虑维护、故障等因素的实际可用程度
|
||||
/// </summary>
|
||||
public decimal AvailabilityRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护事件次数
|
||||
/// </summary>
|
||||
public int MaintenanceEventCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障事件次数
|
||||
/// </summary>
|
||||
public int FaultEventCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作负荷指数(0-100)
|
||||
/// 综合考虑使用率、任务复杂度、时间压力等因素
|
||||
/// </summary>
|
||||
public decimal WorkloadIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 效率评分(0-100)
|
||||
/// 基于任务完成质量、时间准确性等综合评估
|
||||
/// </summary>
|
||||
public decimal EfficiencyScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成本指标
|
||||
/// 包含运行成本、维护成本等
|
||||
/// </summary>
|
||||
public CostMetrics CostMetrics { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 成本指标
|
||||
/// 深度财务分析:设备运行的各项成本统计
|
||||
/// </summary>
|
||||
public class CostMetrics
|
||||
{
|
||||
/// <summary>
|
||||
/// 运行成本(元)
|
||||
/// 包含电费、人工、材料等直接成本
|
||||
/// </summary>
|
||||
public decimal OperatingCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护成本(元)
|
||||
/// </summary>
|
||||
public decimal MaintenanceCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障损失成本(元)
|
||||
/// 包含停机损失、紧急维修等间接成本
|
||||
/// </summary>
|
||||
public decimal FailureCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单位产出成本(元/件)
|
||||
/// 深度业务分析:评估设备经济效益的关键指标
|
||||
/// </summary>
|
||||
public decimal UnitCost { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 趋势分析汇总
|
||||
/// 深度统计分析:提供趋势的整体特征和关键洞察
|
||||
/// </summary>
|
||||
public class TrendAnalysisSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 整体趋势方向
|
||||
/// Increasing: 上升趋势
|
||||
/// Decreasing: 下降趋势
|
||||
/// Stable: 稳定趋势
|
||||
/// Volatile: 波动趋势
|
||||
/// </summary>
|
||||
public string OverallTrend { get; set; } = "Stable";
|
||||
|
||||
/// <summary>
|
||||
/// 趋势强度系数(-1到1,正值表示上升,负值表示下降)
|
||||
/// </summary>
|
||||
public decimal TrendStrength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据波动性系数(0-1,越接近1越不稳定)
|
||||
/// </summary>
|
||||
public decimal VolatilityCoefficient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最高使用率及其时间点
|
||||
/// </summary>
|
||||
public PeakDataPoint PeakUsage { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 最低使用率及其时间点
|
||||
/// </summary>
|
||||
public PeakDataPoint LowUsage { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 平均增长率(月环比或周环比)
|
||||
/// </summary>
|
||||
public decimal AverageGrowthRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 趋势置信度(0-100,基于数据质量和一致性)
|
||||
/// </summary>
|
||||
public decimal TrendConfidence { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关键拐点时间列表
|
||||
/// 深度算法识别:使用统计方法识别趋势变化的关键时刻
|
||||
/// </summary>
|
||||
public List<DateTime> KeyTurningPoints { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 峰值数据点
|
||||
/// </summary>
|
||||
public class PeakDataPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// 峰值时间
|
||||
/// </summary>
|
||||
public DateTime PeakTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 峰值数值
|
||||
/// </summary>
|
||||
public decimal PeakValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 峰值原因分析
|
||||
/// </summary>
|
||||
public string CauseAnalysis { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预测分析结果
|
||||
/// 深度机器学习应用:基于历史数据预测未来趋势
|
||||
/// </summary>
|
||||
public class PredictionAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 预测周期(天数)
|
||||
/// </summary>
|
||||
public int PredictionPeriodDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预测结果数据点
|
||||
/// </summary>
|
||||
public List<PredictionDataPoint> PredictionDataPoints { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 预测模型准确度(0-100)
|
||||
/// 基于历史预测与实际结果的对比
|
||||
/// </summary>
|
||||
public decimal ModelAccuracy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 置信区间范围(百分比)
|
||||
/// </summary>
|
||||
public decimal ConfidenceInterval { get; set; } = 95;
|
||||
|
||||
/// <summary>
|
||||
/// 风险预警列表
|
||||
/// 深度业务智能:基于预测结果识别潜在风险
|
||||
/// </summary>
|
||||
public List<RiskWarning> RiskWarnings { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预测数据点
|
||||
/// </summary>
|
||||
public class PredictionDataPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// 预测时间
|
||||
/// </summary>
|
||||
public DateTime PredictedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预测使用率
|
||||
/// </summary>
|
||||
public decimal PredictedUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预测置信度上限
|
||||
/// </summary>
|
||||
public decimal UpperConfidenceBound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预测置信度下限
|
||||
/// </summary>
|
||||
public decimal LowerConfidenceBound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 影响因子分析
|
||||
/// 列出影响该时间点预测结果的关键因素
|
||||
/// </summary>
|
||||
public List<string> InfluencingFactors { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 风险预警
|
||||
/// 深度业务风控:基于预测分析识别经营风险
|
||||
/// </summary>
|
||||
public class RiskWarning
|
||||
{
|
||||
/// <summary>
|
||||
/// 风险类型
|
||||
/// 如:OverCapacity(超负荷), UnderUtilization(利用率不足), MaintenanceRisk(维护风险)等
|
||||
/// </summary>
|
||||
public string RiskType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 风险等级(Low, Medium, High, Critical)
|
||||
/// </summary>
|
||||
public string RiskLevel { get; set; } = "Medium";
|
||||
|
||||
/// <summary>
|
||||
/// 预计发生时间
|
||||
/// </summary>
|
||||
public DateTime EstimatedOccurrenceTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 风险描述
|
||||
/// </summary>
|
||||
public string RiskDescription { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 建议应对措施
|
||||
/// </summary>
|
||||
public List<string> RecommendedActions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 风险概率(0-100)
|
||||
/// </summary>
|
||||
public decimal RiskProbability { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异常检测结果
|
||||
/// 深度统计分析:基于统计学方法识别异常数据点
|
||||
/// </summary>
|
||||
public class AnomalyDetection
|
||||
{
|
||||
/// <summary>
|
||||
/// 异常发生时间
|
||||
/// </summary>
|
||||
public DateTime AnomalyTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异常类型
|
||||
/// 如:Spike(尖峰), Drop(骤降), Trend(趋势异常), Seasonal(季节性异常)等
|
||||
/// </summary>
|
||||
public string AnomalyType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 异常严重程度(1-10)
|
||||
/// </summary>
|
||||
public int SeverityLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异常值
|
||||
/// </summary>
|
||||
public decimal AnomalyValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 期望值(正常情况下的预期值)
|
||||
/// </summary>
|
||||
public decimal ExpectedValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 偏差程度(百分比)
|
||||
/// </summary>
|
||||
public decimal DeviationPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异常原因推测
|
||||
/// 深度业务分析:结合业务知识推测异常发生的可能原因
|
||||
/// </summary>
|
||||
public List<string> PossibleCauses { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 异常影响评估
|
||||
/// </summary>
|
||||
public string ImpactAssessment { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 季节性分析
|
||||
/// 深度时间序列分析:识别业务的周期性规律
|
||||
/// </summary>
|
||||
public class SeasonalityAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否存在季节性模式
|
||||
/// </summary>
|
||||
public bool HasSeasonalPattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 季节性周期长度(天数)
|
||||
/// </summary>
|
||||
public int SeasonalCycleDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 季节性强度系数(0-1)
|
||||
/// </summary>
|
||||
public decimal SeasonalityStrength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按季节的使用率分布
|
||||
/// </summary>
|
||||
public List<SeasonalUsagePattern> SeasonalPatterns { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 淡旺季分析
|
||||
/// 深度业务洞察:识别生产淡旺季规律
|
||||
/// </summary>
|
||||
public PeakSeasonAnalysis PeakSeasonAnalysis { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 季节性使用模式
|
||||
/// </summary>
|
||||
public class SeasonalUsagePattern
|
||||
{
|
||||
/// <summary>
|
||||
/// 季节名称(春、夏、秋、冬 或 Q1、Q2、Q3、Q4)
|
||||
/// </summary>
|
||||
public string SeasonName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 季节开始时间
|
||||
/// </summary>
|
||||
public DateTime SeasonStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 季节结束时间
|
||||
/// </summary>
|
||||
public DateTime SeasonEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该季节的平均使用率
|
||||
/// </summary>
|
||||
public decimal AverageUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 相对年均值的变化百分比
|
||||
/// </summary>
|
||||
public decimal VariationFromYearlyAverage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该季节的特征描述
|
||||
/// </summary>
|
||||
public string SeasonCharacteristics { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 淡旺季分析
|
||||
/// 深度业务策略支持:为生产计划和资源配置提供决策依据
|
||||
/// </summary>
|
||||
public class PeakSeasonAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 旺季时间段
|
||||
/// </summary>
|
||||
public List<SeasonPeriod> PeakSeasons { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 淡季时间段
|
||||
/// </summary>
|
||||
public List<SeasonPeriod> LowSeasons { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 旺季与淡季的使用率差异百分比
|
||||
/// </summary>
|
||||
public decimal PeakLowDifference { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 季节性规划建议
|
||||
/// 深度业务智慧:基于季节性分析提供运营建议
|
||||
/// </summary>
|
||||
public List<string> SeasonalPlanningRecommendations { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 季节期间
|
||||
/// </summary>
|
||||
public class SeasonPeriod
|
||||
{
|
||||
/// <summary>
|
||||
/// 季节类型(Peak 或 Low)
|
||||
/// </summary>
|
||||
public string SeasonType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 开始时间
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束时间
|
||||
/// </summary>
|
||||
public DateTime EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该期间的平均使用率
|
||||
/// </summary>
|
||||
public decimal AverageUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 持续天数
|
||||
/// </summary>
|
||||
public int DurationDays { get; set; }
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型使用率统计输出模型
|
||||
/// 深度业务场景:支持设备使用效率分析和产能评估
|
||||
/// </summary>
|
||||
public class EquipmentTypeUsageOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型显示名称
|
||||
/// </summary>
|
||||
public string EquipmentTypeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间段
|
||||
/// </summary>
|
||||
public DateTime StatisticsPeriodStart { get; set; }
|
||||
public DateTime StatisticsPeriodEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均使用率(百分比)
|
||||
/// 业务深度思考:基于实际工作时间与理论可用时间的比值
|
||||
/// </summary>
|
||||
public decimal AverageUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 峰值使用率(百分比)
|
||||
/// </summary>
|
||||
public decimal PeakUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最低使用率(百分比)
|
||||
/// </summary>
|
||||
public decimal MinUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总工作时长(小时)
|
||||
/// </summary>
|
||||
public decimal TotalWorkingHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 理论可用时长(小时)
|
||||
/// 深度业务逻辑:考虑设备维护、停机时间后的实际可用时间
|
||||
/// </summary>
|
||||
public decimal TotalAvailableHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备空闲时长(小时)
|
||||
/// </summary>
|
||||
public decimal TotalIdleHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 维护停机时长(小时)
|
||||
/// </summary>
|
||||
public decimal MaintenanceDowntimeHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障停机时长(小时)
|
||||
/// </summary>
|
||||
public decimal FaultDowntimeHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用率趋势分析
|
||||
/// 深度业务场景:支持设备负荷预测和产能规划
|
||||
/// </summary>
|
||||
public UsageTrendAnalysis TrendAnalysis { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 按班次的使用率分布
|
||||
/// </summary>
|
||||
public List<ShiftUsageDistribution> ShiftUsageDistribution { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备使用效率评级
|
||||
/// 业务深度思考:基于使用率、故障率、维护频次的综合评估
|
||||
/// </summary>
|
||||
public EquipmentEfficiencyRating EfficiencyRating { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用率趋势分析
|
||||
/// 深度业务逻辑:基于历史数据分析未来使用趋势
|
||||
/// </summary>
|
||||
public class UsageTrendAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用率变化趋势(相比上期百分比变化)
|
||||
/// </summary>
|
||||
public decimal UsageRateChange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 趋势方向(Increasing, Decreasing, Stable)
|
||||
/// </summary>
|
||||
public string TrendDirection { get; set; } = "Stable";
|
||||
|
||||
/// <summary>
|
||||
/// 预测下期使用率
|
||||
/// </summary>
|
||||
public decimal PredictedUsageRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 趋势置信度(0-100)
|
||||
/// </summary>
|
||||
public decimal TrendConfidence { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 班次使用率分布
|
||||
/// 业务深度思考:支持班次安排优化和人员调度决策
|
||||
/// </summary>
|
||||
public class ShiftUsageDistribution
|
||||
{
|
||||
/// <summary>
|
||||
/// 班次名称
|
||||
/// </summary>
|
||||
public string ShiftName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 班次开始时间
|
||||
/// </summary>
|
||||
public TimeSpan ShiftStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次结束时间
|
||||
/// </summary>
|
||||
public TimeSpan ShiftEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该班次的平均使用率
|
||||
/// </summary>
|
||||
public decimal AverageUsageRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该班次的工作天数
|
||||
/// </summary>
|
||||
public int WorkingDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该班次的总工作小时数
|
||||
/// </summary>
|
||||
public decimal TotalWorkingHours { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备使用效率评级
|
||||
/// 深度业务场景:支持设备性能评估和改进建议
|
||||
/// </summary>
|
||||
public class EquipmentEfficiencyRating
|
||||
{
|
||||
/// <summary>
|
||||
/// 综合效率得分(0-100分)
|
||||
/// 计算逻辑:使用率权重40% + 可用率权重30% + 质量指标权重30%
|
||||
/// </summary>
|
||||
public decimal OverallScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 效率等级(Excellent, Good, Average, Poor)
|
||||
/// </summary>
|
||||
public string EfficiencyGrade { get; set; } = "Average";
|
||||
|
||||
/// <summary>
|
||||
/// 使用率得分(0-100)
|
||||
/// </summary>
|
||||
public decimal UtilizationScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可用率得分(0-100)
|
||||
/// 深度业务逻辑:考虑计划内维护和非计划停机的影响
|
||||
/// </summary>
|
||||
public decimal AvailabilityScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 质量指标得分(0-100)
|
||||
/// 基于故障频次、维护成本等指标
|
||||
/// </summary>
|
||||
public decimal QualityScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 改进建议列表
|
||||
/// </summary>
|
||||
public List<string> ImprovementSuggestions { get; set; } = new();
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备列表输入
|
||||
/// </summary>
|
||||
public class GetEquipmentListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
public string EquipmentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态
|
||||
/// </summary>
|
||||
public int? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称(模糊查询)
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部编号(模糊查询)
|
||||
/// </summary>
|
||||
public string InternalNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备负责人ID
|
||||
/// </summary>
|
||||
public long? ResponsiblePersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序ID
|
||||
/// </summary>
|
||||
public long? ProcessID { get; set; }
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备本地服务接口(专用于SmartSchedule模块)
|
||||
/// </summary>
|
||||
public interface IEquipmentLocalService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取设备列表
|
||||
/// </summary>
|
||||
/// <param name="input">查询条件</param>
|
||||
/// <returns>设备列表</returns>
|
||||
Task<List<EquipmentListOutput>> GetListAsync(GetEquipmentListInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备详情
|
||||
/// </summary>
|
||||
/// <param name="id">设备ID</param>
|
||||
/// <returns>设备详情</returns>
|
||||
Task<EquipmentListOutput> GetAsync(long id);
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <param name="processId">工序ID(可选)</param>
|
||||
/// <returns>可用设备列表</returns>
|
||||
Task<List<EquipmentListOutput>> GetAvailableEquipmentAsync(DateTime date, long? processId = null);
|
||||
|
||||
/// <summary>
|
||||
/// 检查设备是否可用
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>是否可用</returns>
|
||||
Task<bool> IsEquipmentAvailableAsync(long equipmentId, DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取需要维护的设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要维护的设备列表</returns>
|
||||
Task<List<EquipmentListOutput>> GetNeedMaintenanceAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取需要校验的设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要校验的设备列表</returns>
|
||||
Task<List<EquipmentListOutput>> GetNeedCalibrationAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 批量检查设备可用性
|
||||
/// </summary>
|
||||
/// <param name="equipmentIds">设备ID列表</param>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>设备可用性字典</returns>
|
||||
Task<Dictionary<long, bool>> BatchCheckEquipmentAvailabilityAsync(List<long> equipmentIds, DateTime date);
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备服务接口
|
||||
/// 提供设备查询和可用性检查等功能
|
||||
/// </summary>
|
||||
public interface IEquipmentService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定日期的可用设备列表
|
||||
/// </summary>
|
||||
/// <param name="date">查询日期</param>
|
||||
/// <param name="processId">工序ID(可选)</param>
|
||||
/// <returns>可用设备列表</returns>
|
||||
Task<List<EquipmentBasicInfo>> GetAvailableEquipmentAsync(DateTime date, long? processId = null);
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定设备在指定日期是否可用
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <param name="date">检查日期</param>
|
||||
/// <returns>是否可用</returns>
|
||||
Task<bool> IsEquipmentAvailableAsync(long equipmentId, DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期范围内的设备使用统计
|
||||
/// </summary>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>设备使用统计</returns>
|
||||
Task<EquipmentUsageStatistics> GetEquipmentUsageStatisticsAsync(DateTime startDate, DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 批量检查设备可用性
|
||||
/// </summary>
|
||||
/// <param name="equipmentIds">设备ID列表</param>
|
||||
/// <param name="date">检查日期</param>
|
||||
/// <returns>设备可用性结果字典</returns>
|
||||
Task<Dictionary<long, bool>> BatchCheckEquipmentAvailabilityAsync(List<long> equipmentIds, DateTime date);
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Equipment;
|
||||
|
||||
/// <summary>
|
||||
/// 设备统计分析服务接口
|
||||
/// 提供按设备类型的统计分析功能,独立于设备分配业务逻辑
|
||||
/// </summary>
|
||||
public interface IEquipmentStatisticsService
|
||||
{
|
||||
/// <summary>
|
||||
/// 按设备类型统计设备数量和状态分布
|
||||
/// 深度业务场景:支持生产规划时了解各类型设备资源配置情况
|
||||
/// </summary>
|
||||
/// <param name="startDate">统计开始日期</param>
|
||||
/// <param name="endDate">统计结束日期</param>
|
||||
/// <param name="includeInactive">是否包含非活跃设备(报废、停用等)</param>
|
||||
/// <returns>按设备类型分组的统计结果</returns>
|
||||
Task<List<EquipmentTypeStatisticsOutput>> GetEquipmentStatisticsByTypeAsync(
|
||||
DateTime? startDate = null,
|
||||
DateTime? endDate = null,
|
||||
bool includeInactive = false);
|
||||
|
||||
/// <summary>
|
||||
/// 按设备类型统计使用率和工作负荷
|
||||
/// 深度业务场景:支持设备使用效率分析和设备采购决策
|
||||
/// </summary>
|
||||
/// <param name="startDate">统计开始日期</param>
|
||||
/// <param name="endDate">统计结束日期</param>
|
||||
/// <returns>设备类型使用率统计</returns>
|
||||
Task<List<EquipmentTypeUsageOutput>> GetEquipmentUsageByTypeAsync(
|
||||
DateTime startDate,
|
||||
DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 按设备类型统计任务分配情况
|
||||
/// 深度业务场景:支持工艺流程分析和设备负荷均衡评估
|
||||
/// </summary>
|
||||
/// <param name="startDate">统计开始日期</param>
|
||||
/// <param name="endDate">统计结束日期</param>
|
||||
/// <param name="includeCompletedTasks">是否包含已完成任务</param>
|
||||
/// <returns>设备类型任务分配统计</returns>
|
||||
Task<List<EquipmentTypeTaskAllocationOutput>> GetTaskAllocationByTypeAsync(
|
||||
DateTime startDate,
|
||||
DateTime endDate,
|
||||
bool includeCompletedTasks = true);
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备类型趋势分析数据
|
||||
/// 深度业务场景:支持长期设备投资规划和维护策略制定
|
||||
/// </summary>
|
||||
/// <param name="equipmentType">指定设备类型,null则返回所有类型</param>
|
||||
/// <param name="startDate">分析开始日期</param>
|
||||
/// <param name="endDate">分析结束日期</param>
|
||||
/// <param name="groupByPeriod">分组周期:Day, Week, Month</param>
|
||||
/// <returns>设备类型趋势数据</returns>
|
||||
Task<List<EquipmentTypeTrendOutput>> GetEquipmentTypeTrendAsync(
|
||||
string? equipmentType,
|
||||
DateTime startDate,
|
||||
DateTime endDate,
|
||||
string groupByPeriod = "Day");
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备分配服务接口
|
||||
/// </summary>
|
||||
public interface IEquipmentAllocationService
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能设备分配
|
||||
/// </summary>
|
||||
Task<EquipmentAllocationResult> AllocateEquipmentSmartlyAsync(EquipmentAllocationInput input);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备服务客户端接口
|
||||
/// 用于调度模块与EAM设备管理模块之间的通信
|
||||
/// 避免直接依赖EAM模块的服务接口,实现模块解耦
|
||||
/// </summary>
|
||||
public interface IEquipmentClientService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定日期的可用设备列表
|
||||
/// 用于任务整合前的资源充足性检查
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <param name="processId">工序ID(可选,用于筛选特定工序的设备)</param>
|
||||
/// <returns>可用设备列表</returns>
|
||||
Task<List<EquipmentBasicInfo>> GetAvailableEquipmentAsync(DateTime date, long? processId = null);
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定设备在指定日期是否可用
|
||||
/// 用于验证特定设备的可用性状态
|
||||
/// </summary>
|
||||
/// <param name="equipmentId">设备ID</param>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>是否可用</returns>
|
||||
Task<bool> IsEquipmentAvailableAsync(long equipmentId, DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期范围内的设备使用统计
|
||||
/// 用于资源容量计算和负荷分析
|
||||
/// </summary>
|
||||
/// <param name="startDate">开始日期</param>
|
||||
/// <param name="endDate">结束日期</param>
|
||||
/// <returns>设备使用统计信息</returns>
|
||||
Task<EquipmentUsageStatistics> GetEquipmentUsageStatisticsAsync(DateTime startDate, DateTime endDate);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期需要维护的设备列表
|
||||
/// 用于计算维护中不可用的设备数量
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要维护的设备列表</returns>
|
||||
Task<List<EquipmentBasicInfo>> GetMaintenanceEquipmentAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期需要校验的设备列表
|
||||
/// 用于计算校验中不可用的设备数量
|
||||
/// </summary>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>需要校验的设备列表</returns>
|
||||
Task<List<EquipmentBasicInfo>> GetCalibrationEquipmentAsync(DateTime date);
|
||||
|
||||
/// <summary>
|
||||
/// 批量检查设备可用性
|
||||
/// 用于大批量任务的设备资源验证,提高查询效率
|
||||
/// </summary>
|
||||
/// <param name="equipmentIds">设备ID列表</param>
|
||||
/// <param name="date">指定日期</param>
|
||||
/// <returns>设备可用性状态字典,Key为设备ID,Value为是否可用</returns>
|
||||
Task<Dictionary<long, bool>> BatchCheckEquipmentAvailabilityAsync(List<long> equipmentIds, DateTime date);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Internal;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局优化人员分配服务接口
|
||||
/// 基于遗传算法和基尼系数的智能全局优化分配
|
||||
/// </summary>
|
||||
public interface IGlobalPersonnelAllocationService
|
||||
{
|
||||
Task<GlobalAllocationResult> AllocatePersonnelGloballyAsync(GlobalAllocationInput input);
|
||||
|
||||
Task<GlobalAllocationAnalysisResult> AnalyzeAllocationFeasibilityAsync(GlobalAllocationInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 【性能优化】公共的人员可用性计算方法 - 专为遗传算法优化
|
||||
/// 替代原有的反射调用,消除15-20%的性能开销
|
||||
/// </summary>
|
||||
Task<double> CalculatePersonnelAvailabilityForGeneticAsync(
|
||||
GlobalPersonnelInfo personnel, WorkOrderEntity task, List<WorkOrderEntity> contextTasks);
|
||||
|
||||
/// <summary>
|
||||
/// 【性能优化】公共的班次规则合规性评分方法 - 专为遗传算法优化
|
||||
/// 替代原有的反射调用,提升约束检查性能
|
||||
/// </summary>
|
||||
Task<double> CalculateShiftRuleComplianceForGeneticAsync(
|
||||
long personnelId, DateTime workDate, long shiftId, GlobalAllocationContext context);
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录服务接口
|
||||
/// </summary>
|
||||
public interface IIntegrationRecordService
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成整合记录
|
||||
/// </summary>
|
||||
Task<IntegrationRecord> GenerateIntegrationRecordAsync(IntegrationRecordInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 根据记录ID查询整合记录信息并附加任务集
|
||||
/// </summary>
|
||||
/// <param name="recordId">整合记录ID</param>
|
||||
/// <returns>包含任务集的整合记录信息</returns>
|
||||
Task<IntegrationRecordWithTasksOutput> GetIntegrationRecordWithTasksAsync(long recordId);
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有整合记录列表
|
||||
/// </summary>
|
||||
/// <param name="input">查询条件</param>
|
||||
/// <returns>整合记录列表</returns>
|
||||
Task<List<IntegrationRecordListOutput>> GetIntegrationRecordsAsync(IntegrationRecordGetListInput input);
|
||||
|
||||
#region 发布管理接口
|
||||
|
||||
/// <summary>
|
||||
/// 发布整合记录
|
||||
/// 将草稿状态的整合记录发布生效,更新任务分配状态
|
||||
/// </summary>
|
||||
/// <param name="input">发布输入参数</param>
|
||||
/// <returns>发布结果</returns>
|
||||
Task<PublishIntegrationRecordResult> PublishIntegrationRecordAsync(PublishIntegrationRecordInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 更新整合记录状态
|
||||
/// 支持状态转换:草稿->已发布->已完成->已撤销
|
||||
/// </summary>
|
||||
/// <param name="recordId">整合记录ID</param>
|
||||
/// <param name="newStatus">新状态</param>
|
||||
/// <param name="operatorUserId">操作员用户ID</param>
|
||||
/// <param name="operatorName">操作员姓名</param>
|
||||
/// <param name="remarks">状态更新说明</param>
|
||||
/// <returns>更新结果</returns>
|
||||
Task<bool> UpdateIntegrationRecordStatusAsync(long recordId, string newStatus, long operatorUserId, string operatorName, string remarks = "");
|
||||
|
||||
/// <summary>
|
||||
/// 发布修改后的任务
|
||||
/// 将任务的修改内容发布到生产系统
|
||||
/// </summary>
|
||||
/// <param name="recordId">整合记录ID</param>
|
||||
/// <param name="modifiedTaskIds">修改的任务ID列表</param>
|
||||
/// <param name="operatorUserId">操作员用户ID</param>
|
||||
/// <param name="operatorName">操作员姓名</param>
|
||||
/// <param name="publishRemarks">发布说明</param>
|
||||
/// <returns>发布结果</returns>
|
||||
Task<PublishIntegrationRecordResult> PublishTaskModificationsAsync(long recordId, List<long> modifiedTaskIds, long operatorUserId, string operatorName, string publishRemarks = "");
|
||||
|
||||
#endregion
|
||||
|
||||
#region 通知管理接口(预留)
|
||||
|
||||
/// <summary>
|
||||
/// 发送发布通知(预留接口)
|
||||
/// 向相关人员发送整合记录发布的通知信息
|
||||
/// </summary>
|
||||
/// <param name="recordId">整合记录ID</param>
|
||||
/// <param name="notificationType">通知类型</param>
|
||||
/// <param name="targetPersonnelIds">目标人员ID列表</param>
|
||||
/// <param name="customMessage">自定义消息</param>
|
||||
/// <returns>通知发送结果</returns>
|
||||
Task<NotificationSendResult> SendPublishNotificationAsync(long recordId, string notificationType, List<long> targetPersonnelIds, string customMessage = "");
|
||||
|
||||
/// <summary>
|
||||
/// 创建待办任务(预留接口)
|
||||
/// 为相关人员创建与发布记录相关的待办任务
|
||||
/// </summary>
|
||||
/// <param name="recordId">整合记录ID</param>
|
||||
/// <param name="todoType">待办类型</param>
|
||||
/// <param name="assigneeIds">负责人ID列表</param>
|
||||
/// <param name="title">待办标题</param>
|
||||
/// <param name="description">待办描述</param>
|
||||
/// <param name="dueDate">截止时间</param>
|
||||
/// <returns>创建结果</returns>
|
||||
Task<CreateTodoResult> CreatePublishRelatedTodoAsync(long recordId, string todoType, List<long> assigneeIds, string title, string description, DateTime? dueDate = null);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员分配服务接口
|
||||
/// </summary>
|
||||
public interface IPersonnelAllocationService
|
||||
{
|
||||
Task<PersonnelAllocationResult> AllocatePersonnelSmartlyAsync(PersonnelAllocationInput input);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration;
|
||||
|
||||
public interface ISmartScheduleOrchestratorService
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务整合前自检服务接口
|
||||
/// </summary>
|
||||
public interface ITaskIntegrationPreCheckService
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载待整合的任务列表,支持多项目号筛选,按项目号分组展示
|
||||
/// </summary>
|
||||
Task<TaskIntegrationListOutput> LoadPendingIntegrationTasksAsync(LoadPendingTasksInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 对勾选的项目和任务进行整合前自检
|
||||
/// </summary>
|
||||
Task<TaskIntegrationPreCheckResult> ExecutePreCheckAsync(TaskIntegrationPreCheckInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取项目任务数量与可用人员数量对比(按日和周)
|
||||
/// </summary>
|
||||
Task<ProjectResourceComparisonResult> GetProjectResourceComparisonAsync(ProjectResourceComparisonInput input);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务验证服务接口
|
||||
/// </summary>
|
||||
public interface ITaskValidationService
|
||||
{
|
||||
/// <summary>
|
||||
/// 分析任务需求
|
||||
/// </summary>
|
||||
Task<TaskRequirementAnalysisResult> AnalyzeTaskRequirementsAsync(List<WorkOrderEntity> tasks);
|
||||
|
||||
/// <summary>
|
||||
/// 验证任务数据完整性
|
||||
/// </summary>
|
||||
Task<TaskDataValidationResult> ValidateTaskDataIntegrityAsync(List<WorkOrderEntity> tasks);
|
||||
|
||||
/// <summary>
|
||||
/// 加载任务详细信息
|
||||
/// </summary>
|
||||
Task<TaskDetailLoadResult> LoadTaskDetailedInfoAsync(List<WorkOrderEntity> tasks);
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销整合记录输入参数
|
||||
/// 包含撤销操作的所有必要信息和业务规则
|
||||
///
|
||||
/// 业务思考:
|
||||
/// 1. 撤销是发布后的逆向操作,需要严格的权限控制
|
||||
/// 2. 撤销会将任务状态从Assigned回退到PendingIntegration
|
||||
/// 3. 撤销操作必须记录详细的审计信息
|
||||
/// 4. 支持部分撤销,提高操作的灵活性
|
||||
/// </summary>
|
||||
public class CancelIntegrationRecordInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "整合记录ID不能为空")]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "整合记录ID必须大于0")]
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销操作员用户ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "撤销操作员用户ID不能为空")]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "撤销操作员用户ID必须大于0")]
|
||||
public long CancelledByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销操作员用户名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "撤销操作员用户名不能为空")]
|
||||
[StringLength(50, ErrorMessage = "撤销操作员用户名长度不能超过50个字符")]
|
||||
public string CancelledByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销原因
|
||||
/// 必填字段,用于审计和问题追踪
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "撤销原因不能为空")]
|
||||
[StringLength(500, ErrorMessage = "撤销原因长度不能超过500个字符")]
|
||||
public string CancelReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制撤销
|
||||
/// 当存在已开始执行的任务时,是否强制撤销
|
||||
/// 需要更高级别的权限
|
||||
/// </summary>
|
||||
public bool ForceCancelInProgressTasks { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否通知相关人员
|
||||
/// 撤销后是否通知已分配的人员和设备管理员
|
||||
/// </summary>
|
||||
public bool NotifyRelatedPersonnel { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销范围限制
|
||||
/// 指定只撤销特定任务,null表示撤销整合记录中的所有任务
|
||||
///
|
||||
/// 业务价值:
|
||||
/// - 支持部分撤销功能,提高撤销的灵活性
|
||||
/// - 当某些任务需要重新分配时,可以单独撤销
|
||||
/// - 减少对正常执行任务的影响
|
||||
/// </summary>
|
||||
public List<long>? SpecificTaskIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销后处理方式
|
||||
/// 控制撤销后任务的处理方式
|
||||
/// </summary>
|
||||
public CancelAfterProcessingType AfterProcessingType { get; set; } = CancelAfterProcessingType.ReturnToPendingIntegration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销后处理方式枚举
|
||||
/// </summary>
|
||||
public enum CancelAfterProcessingType
|
||||
{
|
||||
/// <summary>
|
||||
/// 回退到待整合状态
|
||||
/// 任务状态回退到PendingIntegration,等待重新整合
|
||||
/// </summary>
|
||||
ReturnToPendingIntegration = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 标记为需要重新分配
|
||||
/// 任务保持在特殊状态,需要手动处理
|
||||
/// </summary>
|
||||
MarkForReassignment = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 暂停任务
|
||||
/// 将任务状态设置为暂停,等待进一步决策
|
||||
/// </summary>
|
||||
PauseTasks = 2
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局优化分配输入
|
||||
/// </summary>
|
||||
public class GlobalAllocationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 待分配的任务ID列表(当Tasks为空时使用)
|
||||
/// </summary>
|
||||
public List<long> TaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 待分配的任务对象列表(性能优化:避免重复数据库查询)
|
||||
/// </summary>
|
||||
public List<WorkOrderEntity> Tasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 排除的人员ID列表
|
||||
/// </summary>
|
||||
public List<long> ExcludedPersonnelIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 全局优化配置
|
||||
/// </summary>
|
||||
public GlobalOptimizationConfig OptimizationConfig { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局优化配置
|
||||
/// </summary>
|
||||
public class GlobalOptimizationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 遗传算法种群大小
|
||||
/// 生产环境推荐:小规模(20任务)使用50-100,中规模(50-100任务)使用80-150
|
||||
/// </summary>
|
||||
[Range(50, 500, ErrorMessage = "种群大小应在50-500之间")]
|
||||
public int PopulationSize { get; set; } = 100; // 从200降低到100,适合100任务规模
|
||||
|
||||
/// <summary>
|
||||
/// 最大迭代代数
|
||||
/// 生产环境推荐:由于预筛选机制,可以适当减少迭代次数
|
||||
/// </summary>
|
||||
[Range(20, 200, ErrorMessage = "迭代代数应在20-200之间")]
|
||||
public int MaxGenerations { get; set; } = 60; // 从100降低到60,在质量和性能间平衡
|
||||
|
||||
/// <summary>
|
||||
/// 最大执行时间(秒)
|
||||
/// 生产环境:为100任务增加更宽裕的时间限制
|
||||
/// </summary>
|
||||
[Range(5, 300, ErrorMessage = "执行时间应在5-300秒之间")]
|
||||
public int MaxExecutionTimeSeconds { get; set; } = 120; // 从30秒增加到120秒,适应100任务的复杂度
|
||||
|
||||
/// <summary>
|
||||
/// 基尼系数公平性权重(0-1)
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "公平性权重应在0-1之间")]
|
||||
public double FairnessWeight { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 约束满足权重(0-1)
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "约束权重应在0-1之间")]
|
||||
public double ConstraintWeight { get; set; } = 0.6;
|
||||
|
||||
/// <summary>
|
||||
/// 资质匹配权重(0-1)
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "资质权重应在0-1之间")]
|
||||
public double QualificationWeight { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用智能协商
|
||||
/// </summary>
|
||||
public bool EnableIntelligentNegotiation { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 收敛阈值
|
||||
/// </summary>
|
||||
[Range(0.001, 0.1, ErrorMessage = "收敛阈值应在0.001-0.1之间")]
|
||||
public double ConvergenceThreshold { get; set; } = 0.001;
|
||||
|
||||
/// <summary>
|
||||
/// 创建适合生产环境的优化配置
|
||||
/// 适用7天100任务30人员的大规模调度场景
|
||||
/// </summary>
|
||||
/// <param name="taskCount">任务数量</param>
|
||||
/// <param name="personnelCount">人员数量</param>
|
||||
/// <returns>优化后的配置</returns>
|
||||
public static GlobalOptimizationConfig CreateProductionConfig(int taskCount, int personnelCount)
|
||||
{
|
||||
var config = new GlobalOptimizationConfig();
|
||||
|
||||
// 根据任务规模动态调整参数
|
||||
if (taskCount <= 20)
|
||||
{
|
||||
// 小规模:超快速模式(针对6个任务优化)
|
||||
if (taskCount <= 6)
|
||||
{
|
||||
config.PopulationSize = 15; // 从50降到15,减少计算量
|
||||
config.MaxGenerations = 10; // 从30降到10,快速收敛
|
||||
config.MaxExecutionTimeSeconds = 15; // 从60降到15秒
|
||||
}
|
||||
else
|
||||
{
|
||||
config.PopulationSize = 30; // 7-20任务使用中等参数
|
||||
config.MaxGenerations = 20;
|
||||
config.MaxExecutionTimeSeconds = 30;
|
||||
}
|
||||
}
|
||||
else if (taskCount <= 50)
|
||||
{
|
||||
// 中规模:平衡模式
|
||||
config.PopulationSize = 80;
|
||||
config.MaxGenerations = 50;
|
||||
config.MaxExecutionTimeSeconds = 90;
|
||||
}
|
||||
else if (taskCount <= 100)
|
||||
{
|
||||
// 大规模:高质量模式(适合生产环境)
|
||||
config.PopulationSize = 100;
|
||||
config.MaxGenerations = 60;
|
||||
config.MaxExecutionTimeSeconds = 120;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 超大规模:保守模式
|
||||
config.PopulationSize = Math.Min(150, taskCount + 50);
|
||||
config.MaxGenerations = 80;
|
||||
config.MaxExecutionTimeSeconds = 180;
|
||||
}
|
||||
|
||||
// 根据人员数量调整权重
|
||||
if (personnelCount < 20)
|
||||
{
|
||||
// 人员较少,提高公平性权重
|
||||
config.FairnessWeight = 0.4;
|
||||
config.ConstraintWeight = 0.5;
|
||||
config.QualificationWeight = 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 人员充足,保持默认权重
|
||||
config.FairnessWeight = 0.3;
|
||||
config.ConstraintWeight = 0.6;
|
||||
config.QualificationWeight = 0.1;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建快速测试配置(用于开发和测试环境)
|
||||
/// </summary>
|
||||
/// <returns>快速测试配置</returns>
|
||||
public static GlobalOptimizationConfig CreateFastTestConfig()
|
||||
{
|
||||
return new GlobalOptimizationConfig
|
||||
{
|
||||
PopulationSize = 30,
|
||||
MaxGenerations = 20,
|
||||
MaxExecutionTimeSeconds = 30,
|
||||
FairnessWeight = 0.2,
|
||||
ConstraintWeight = 0.7,
|
||||
QualificationWeight = 0.1,
|
||||
ConvergenceThreshold = 0.01 // 更宽松的收敛条件以加速测试
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建高质量配置(用于关键业务场景)
|
||||
/// </summary>
|
||||
/// <returns>高质量配置</returns>
|
||||
public static GlobalOptimizationConfig CreateHighQualityConfig()
|
||||
{
|
||||
return new GlobalOptimizationConfig
|
||||
{
|
||||
PopulationSize = 200,
|
||||
MaxGenerations = 100,
|
||||
MaxExecutionTimeSeconds = 300,
|
||||
FairnessWeight = 0.35,
|
||||
ConstraintWeight = 0.55,
|
||||
QualificationWeight = 0.1,
|
||||
ConvergenceThreshold = 0.0005
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录列表查询输入
|
||||
/// </summary>
|
||||
public class IntegrationRecordGetListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合批次编码
|
||||
/// </summary>
|
||||
public string IntegrationBatchCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目编号
|
||||
/// </summary>
|
||||
public string ProjectNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户名
|
||||
/// </summary>
|
||||
public string OperatorUserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员真实姓名
|
||||
/// </summary>
|
||||
public string OperatorRealName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始日期
|
||||
/// </summary>
|
||||
public DateTime? StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束日期
|
||||
/// </summary>
|
||||
public DateTime? EndDate { get; set; }
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录任务修改输入
|
||||
/// 用于手动修改整合记录中的任务分配信息
|
||||
/// </summary>
|
||||
public class IntegrationRecordTaskModifyInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户ID
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户名
|
||||
/// </summary>
|
||||
public string OperatorUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务修改列表
|
||||
/// </summary>
|
||||
public List<TaskModificationInput> TaskModifications { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 修改原因说明
|
||||
/// </summary>
|
||||
public string ModificationReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制执行(忽略部分警告)
|
||||
/// </summary>
|
||||
public bool ForceExecute { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单个任务修改输入
|
||||
/// </summary>
|
||||
public class TaskModificationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码(可选,用于显示)
|
||||
/// </summary>
|
||||
public string? TaskCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新的人员ID(可选)
|
||||
/// </summary>
|
||||
public long? NewPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新的人员姓名(可选)
|
||||
/// </summary>
|
||||
public string? NewPersonnelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新的设备ID(可选)
|
||||
/// </summary>
|
||||
public long? NewEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新的设备名称(可选)
|
||||
/// </summary>
|
||||
public string? NewEquipmentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改备注
|
||||
/// </summary>
|
||||
public string ModificationNote { get; set; } = string.Empty;
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载待整合任务输入
|
||||
/// </summary>
|
||||
public class LoadPendingTasksInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目号列表(支持多个项目号筛选)
|
||||
/// </summary>
|
||||
public List<string> ProjectNumbers { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 任务日期范围
|
||||
/// </summary>
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工序代码列表
|
||||
/// </summary>
|
||||
public List<string> ProcessCodes { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 班次ID列表
|
||||
/// </summary>
|
||||
public List<long> ShiftIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态(默认查询待整合状态)
|
||||
/// </summary>
|
||||
public WorkOrderStatusEnum Status { get; set; } = WorkOrderStatusEnum.PendingIntegration;
|
||||
|
||||
/// <summary>
|
||||
/// 分页参数
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 50;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务整合前自检输入
|
||||
/// </summary>
|
||||
public class TaskIntegrationPreCheckInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 选中的项目号列表
|
||||
/// </summary>
|
||||
public List<string> SelectedProjectNumbers { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 选中的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> SelectedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否检查人员资源充足性
|
||||
/// </summary>
|
||||
public bool CheckPersonnelSufficiency { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否检查设备资源充足性
|
||||
/// </summary>
|
||||
public bool CheckEquipmentSufficiency { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 检查的时间范围(按日和周)
|
||||
/// </summary>
|
||||
public DateTime CheckStartDate { get; set; }
|
||||
public DateTime CheckEndDate { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 项目资源对比输入
|
||||
/// </summary>
|
||||
public class ProjectResourceComparisonInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目号列表
|
||||
/// </summary>
|
||||
public List<string> ProjectNumbers { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 对比时间范围
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对比维度(按日、按周)
|
||||
/// </summary>
|
||||
public ComparisonDimension Dimension { get; set; } = ComparisonDimension.Daily;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对比维度枚举
|
||||
/// </summary>
|
||||
public enum ComparisonDimension
|
||||
{
|
||||
/// <summary>
|
||||
/// 按日对比
|
||||
/// </summary>
|
||||
Daily = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 按周对比
|
||||
/// </summary>
|
||||
Weekly = 2
|
||||
}
|
||||
}
|
@ -0,0 +1,805 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能人员分配优化权重配置
|
||||
/// 五层决策模型第三层:优化决策阶段的核心权重配置
|
||||
/// 支持多策略、多场景、动态调整的智能权重管理
|
||||
/// 深度业务思考:平衡效率、公平性、连续性、专业性等多维度目标
|
||||
/// </summary>
|
||||
public class OptimizationWeights
|
||||
{
|
||||
#region 核心权重配置
|
||||
|
||||
/// <summary>
|
||||
/// 指定人员优先权重 (0.0-1.0)
|
||||
/// 业务含义:当任务有明确指定人员时的优先级权重
|
||||
/// 适用场景:特殊技能需求、客户指定、专项任务等
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "指定人员权重必须在0.0-1.0范围内")]
|
||||
public double AssignedPersonnelWeight { get; set; } = 0.8;
|
||||
|
||||
/// <summary>
|
||||
/// 项目FL人员优先权重 (0.0-1.0)
|
||||
/// 业务含义:项目内部FL(First Line)人员的优先级权重
|
||||
/// 适用场景:项目连续性、知识传承、团队稳定性
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "项目FL人员权重必须在0.0-1.0范围内")]
|
||||
public double ProjectFLWeight { get; set; } = 0.6;
|
||||
|
||||
/// <summary>
|
||||
/// 工作负载均衡权重 (0.0-1.0)
|
||||
/// 业务含义:人员工作负载分布均衡的重要性权重
|
||||
/// 适用场景:公平分配、避免过劳、提升团队稳定性
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "工作负载均衡权重必须在0.0-1.0范围内")]
|
||||
public double WorkloadBalanceWeight { get; set; } = 0.4;
|
||||
|
||||
/// <summary>
|
||||
/// 班次连续性权重 (0.0-1.0)
|
||||
/// 业务含义:保持人员班次连续性和规律性的权重
|
||||
/// 适用场景:生物钟保护、工作效率优化、人员健康管理
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "班次连续性权重必须在0.0-1.0范围内")]
|
||||
public double ShiftContinuityWeight { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配优先权重 (0.0-1.0)
|
||||
/// 业务含义:人员技能与任务需求匹配度的权重
|
||||
/// 适用场景:质量保证、效率提升、风险控制
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "技能匹配权重必须在0.0-1.0范围内")]
|
||||
public double SkillMatchWeight { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// 协作历史权重 (0.0-1.0)
|
||||
/// 业务含义:人员在相关项目的历史协作经验权重
|
||||
/// 适用场景:团队默契、沟通效率、项目风险降低
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "协作历史权重必须在0.0-1.0范围内")]
|
||||
public double CollaborationHistoryWeight { get; set; } = 0.2;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 扩展权重配置
|
||||
|
||||
/// <summary>
|
||||
/// 成本效益权重 (0.0-1.0)
|
||||
/// 业务含义:考虑人员成本与任务价值匹配的权重
|
||||
/// 适用场景:成本控制、资源优化配置、ROI最大化
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "成本效益权重必须在0.0-1.0范围内")]
|
||||
public double CostEfficiencyWeight { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 地理位置便利性权重 (0.0-1.0)
|
||||
/// 业务含义:人员地理位置与工作地点便利性的权重
|
||||
/// 适用场景:交通成本、响应速度、突发事件处理
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "地理位置便利性权重必须在0.0-1.0范围内")]
|
||||
public double LocationConvenienceWeight { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 培训发展权重 (0.0-1.0)
|
||||
/// 业务含义:为人员提供学习和发展机会的权重
|
||||
/// 适用场景:人才培养、技能提升、职业发展规划
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "培训发展权重必须在0.0-1.0范围内")]
|
||||
public double TrainingDevelopmentWeight { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 紧急响应能力权重 (0.0-1.0)
|
||||
/// 业务含义:人员处理紧急情况能力的权重
|
||||
/// 适用场景:应急任务、关键节点、风险管控
|
||||
/// </summary>
|
||||
[Range(0.0, 1.0, ErrorMessage = "紧急响应能力权重必须在0.0-1.0范围内")]
|
||||
public double EmergencyResponseWeight { get; set; } = 0.4;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 权重配置元数据
|
||||
|
||||
/// <summary>
|
||||
/// 权重配置名称
|
||||
/// 用于识别和管理不同的权重配置方案
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "权重配置名称不能为空")]
|
||||
[StringLength(100, ErrorMessage = "权重配置名称长度不能超过100字符")]
|
||||
public string ConfigurationName { get; set; } = "默认配置";
|
||||
|
||||
/// <summary>
|
||||
/// 权重配置描述
|
||||
/// 详细说明该配置的适用场景和特点
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "权重配置描述长度不能超过500字符")]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 配置策略类型
|
||||
/// 标识该权重配置所属的分配策略类型
|
||||
/// </summary>
|
||||
public OptimizationStrategy StrategyType { get; set; } = OptimizationStrategy.Balanced;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为系统预设配置
|
||||
/// 标识是否为系统内置的标准配置
|
||||
/// </summary>
|
||||
public bool IsSystemPreset { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 配置创建者ID
|
||||
/// 记录创建该配置的用户或系统标识
|
||||
/// </summary>
|
||||
public long? CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 配置创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 最后修改时间
|
||||
/// </summary>
|
||||
public DateTime LastModifiedTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 配置版本号
|
||||
/// 用于跟踪配置的变更历史
|
||||
/// </summary>
|
||||
public string Version { get; set; } = "1.0.0";
|
||||
|
||||
#endregion
|
||||
|
||||
#region 高级配置选项
|
||||
|
||||
/// <summary>
|
||||
/// 自定义权重规则
|
||||
/// 支持用户定义的特殊权重计算规则
|
||||
/// </summary>
|
||||
public Dictionary<string, CustomWeightRule> CustomWeightRules { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 权重动态调整配置
|
||||
/// 根据实时条件动态调整权重的规则配置
|
||||
/// </summary>
|
||||
public DynamicWeightAdjustment DynamicAdjustment { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 权重约束条件
|
||||
/// 定义权重配置必须满足的约束条件
|
||||
/// </summary>
|
||||
public WeightConstraints Constraints { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 权重归一化方式
|
||||
/// 定义如何对权重进行标准化处理
|
||||
/// </summary>
|
||||
public WeightNormalizationMethod NormalizationMethod { get; set; } = WeightNormalizationMethod.ProportionalSum;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 核心业务方法
|
||||
|
||||
/// <summary>
|
||||
/// 验证权重配置的有效性
|
||||
/// 深度业务思考:确保权重配置符合业务逻辑和数学约束
|
||||
/// </summary>
|
||||
public WeightValidationResult ValidateConfiguration()
|
||||
{
|
||||
var result = new WeightValidationResult { IsValid = true, Issues = new List<string>() };
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 基础范围验证(通过DataAnnotations已覆盖)
|
||||
var properties = GetType().GetProperties()
|
||||
.Where(p => p.PropertyType == typeof(double) && p.Name.EndsWith("Weight"));
|
||||
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
var value = (double)prop.GetValue(this);
|
||||
if (value < 0.0 || value > 1.0)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"{prop.Name} 值 {value} 超出有效范围 [0.0, 1.0]");
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 权重总和合理性检查
|
||||
var totalWeight = GetTotalWeight();
|
||||
if (totalWeight < 0.1)
|
||||
{
|
||||
result.Issues.Add($"权重总和过低 ({totalWeight:F2}),可能导致分配结果不稳定");
|
||||
}
|
||||
else if (totalWeight > 5.0)
|
||||
{
|
||||
result.Issues.Add($"权重总和过高 ({totalWeight:F2}),建议进行归一化处理");
|
||||
}
|
||||
|
||||
// 3. 业务逻辑一致性检查
|
||||
if (AssignedPersonnelWeight < 0.5 && StrategyType == OptimizationStrategy.AssignedPersonnelFirst)
|
||||
{
|
||||
result.Issues.Add("指定人员优先策略下,指定人员权重应不低于0.5");
|
||||
}
|
||||
|
||||
if (WorkloadBalanceWeight < 0.6 && StrategyType == OptimizationStrategy.LoadBalanceFirst)
|
||||
{
|
||||
result.Issues.Add("负载均衡优先策略下,工作负载均衡权重应不低于0.6");
|
||||
}
|
||||
|
||||
// 4. 约束条件检查
|
||||
if (Constraints != null)
|
||||
{
|
||||
var constraintResult = Constraints.ValidateConstraints(this);
|
||||
if (!constraintResult.IsValid)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.AddRange(constraintResult.Issues);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"权重配置验证异常:{ex.Message}");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取权重总和
|
||||
/// </summary>
|
||||
public double GetTotalWeight()
|
||||
{
|
||||
return AssignedPersonnelWeight + ProjectFLWeight + WorkloadBalanceWeight +
|
||||
ShiftContinuityWeight + SkillMatchWeight + CollaborationHistoryWeight +
|
||||
CostEfficiencyWeight + LocationConvenienceWeight + TrainingDevelopmentWeight +
|
||||
EmergencyResponseWeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 归一化权重配置
|
||||
/// 将所有权重按比例调整到指定的总和
|
||||
/// </summary>
|
||||
public void NormalizeWeights(double targetSum = 1.0)
|
||||
{
|
||||
var currentSum = GetTotalWeight();
|
||||
if (currentSum <= 0) return;
|
||||
|
||||
var factor = targetSum / currentSum;
|
||||
|
||||
AssignedPersonnelWeight *= factor;
|
||||
ProjectFLWeight *= factor;
|
||||
WorkloadBalanceWeight *= factor;
|
||||
ShiftContinuityWeight *= factor;
|
||||
SkillMatchWeight *= factor;
|
||||
CollaborationHistoryWeight *= factor;
|
||||
CostEfficiencyWeight *= factor;
|
||||
LocationConvenienceWeight *= factor;
|
||||
TrainingDevelopmentWeight *= factor;
|
||||
EmergencyResponseWeight *= factor;
|
||||
|
||||
LastModifiedTime = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为字典格式
|
||||
/// 用于与现有系统的权重配置格式兼容
|
||||
/// </summary>
|
||||
public Dictionary<string, double> ToDictionary()
|
||||
{
|
||||
return new Dictionary<string, double>
|
||||
{
|
||||
["AssignedPersonnel"] = AssignedPersonnelWeight,
|
||||
["ProjectFL"] = ProjectFLWeight,
|
||||
["WorkloadBalance"] = WorkloadBalanceWeight,
|
||||
["ShiftContinuity"] = ShiftContinuityWeight,
|
||||
["SkillMatch"] = SkillMatchWeight,
|
||||
["CollaborationHistory"] = CollaborationHistoryWeight,
|
||||
["CostEfficiency"] = CostEfficiencyWeight,
|
||||
["LocationConvenience"] = LocationConvenienceWeight,
|
||||
["TrainingDevelopment"] = TrainingDevelopmentWeight,
|
||||
["EmergencyResponse"] = EmergencyResponseWeight
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从字典加载权重配置
|
||||
/// </summary>
|
||||
public void LoadFromDictionary(Dictionary<string, double> weights)
|
||||
{
|
||||
if (weights == null) return;
|
||||
|
||||
AssignedPersonnelWeight = weights.GetValueOrDefault("AssignedPersonnel", AssignedPersonnelWeight);
|
||||
ProjectFLWeight = weights.GetValueOrDefault("ProjectFL", ProjectFLWeight);
|
||||
WorkloadBalanceWeight = weights.GetValueOrDefault("WorkloadBalance", WorkloadBalanceWeight);
|
||||
ShiftContinuityWeight = weights.GetValueOrDefault("ShiftContinuity", ShiftContinuityWeight);
|
||||
SkillMatchWeight = weights.GetValueOrDefault("SkillMatch", SkillMatchWeight);
|
||||
CollaborationHistoryWeight = weights.GetValueOrDefault("CollaborationHistory", CollaborationHistoryWeight);
|
||||
CostEfficiencyWeight = weights.GetValueOrDefault("CostEfficiency", CostEfficiencyWeight);
|
||||
LocationConvenienceWeight = weights.GetValueOrDefault("LocationConvenience", LocationConvenienceWeight);
|
||||
TrainingDevelopmentWeight = weights.GetValueOrDefault("TrainingDevelopment", TrainingDevelopmentWeight);
|
||||
EmergencyResponseWeight = weights.GetValueOrDefault("EmergencyResponse", EmergencyResponseWeight);
|
||||
|
||||
LastModifiedTime = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 深拷贝权重配置
|
||||
/// </summary>
|
||||
public OptimizationWeights DeepClone()
|
||||
{
|
||||
return new OptimizationWeights
|
||||
{
|
||||
AssignedPersonnelWeight = AssignedPersonnelWeight,
|
||||
ProjectFLWeight = ProjectFLWeight,
|
||||
WorkloadBalanceWeight = WorkloadBalanceWeight,
|
||||
ShiftContinuityWeight = ShiftContinuityWeight,
|
||||
SkillMatchWeight = SkillMatchWeight,
|
||||
CollaborationHistoryWeight = CollaborationHistoryWeight,
|
||||
CostEfficiencyWeight = CostEfficiencyWeight,
|
||||
LocationConvenienceWeight = LocationConvenienceWeight,
|
||||
TrainingDevelopmentWeight = TrainingDevelopmentWeight,
|
||||
EmergencyResponseWeight = EmergencyResponseWeight,
|
||||
ConfigurationName = ConfigurationName + "_Copy",
|
||||
Description = Description,
|
||||
StrategyType = StrategyType,
|
||||
IsSystemPreset = false,
|
||||
CreatedBy = CreatedBy,
|
||||
CreatedTime = DateTime.Now,
|
||||
LastModifiedTime = DateTime.Now,
|
||||
Version = "1.0.0",
|
||||
CustomWeightRules = new Dictionary<string, CustomWeightRule>(CustomWeightRules),
|
||||
DynamicAdjustment = DynamicAdjustment?.DeepClone(),
|
||||
Constraints = Constraints?.DeepClone(),
|
||||
NormalizationMethod = NormalizationMethod
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 预设配置工厂方法
|
||||
|
||||
/// <summary>
|
||||
/// 创建效率优先配置
|
||||
/// 适用场景:紧急任务、关键交付、高价值项目
|
||||
/// </summary>
|
||||
public static OptimizationWeights CreateEfficiencyFirstConfiguration()
|
||||
{
|
||||
return new OptimizationWeights
|
||||
{
|
||||
ConfigurationName = "效率优先配置",
|
||||
Description = "优先考虑技能匹配和协作历史,适用于紧急任务和关键交付",
|
||||
StrategyType = OptimizationStrategy.EfficiencyFirst,
|
||||
IsSystemPreset = true,
|
||||
AssignedPersonnelWeight = 0.9,
|
||||
SkillMatchWeight = 0.8,
|
||||
CollaborationHistoryWeight = 0.7,
|
||||
ProjectFLWeight = 0.6,
|
||||
EmergencyResponseWeight = 0.8,
|
||||
WorkloadBalanceWeight = 0.2,
|
||||
ShiftContinuityWeight = 0.2,
|
||||
CostEfficiencyWeight = 0.3,
|
||||
LocationConvenienceWeight = 0.1,
|
||||
TrainingDevelopmentWeight = 0.1
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建公平分配配置
|
||||
/// 适用场景:日常任务、团队建设、长期项目
|
||||
/// </summary>
|
||||
public static OptimizationWeights CreateFairDistributionConfiguration()
|
||||
{
|
||||
return new OptimizationWeights
|
||||
{
|
||||
ConfigurationName = "公平分配配置",
|
||||
Description = "注重工作负载均衡和培训发展,适用于日常任务和团队建设",
|
||||
StrategyType = OptimizationStrategy.FairDistribution,
|
||||
IsSystemPreset = true,
|
||||
WorkloadBalanceWeight = 0.8,
|
||||
TrainingDevelopmentWeight = 0.6,
|
||||
SkillMatchWeight = 0.5,
|
||||
ShiftContinuityWeight = 0.5,
|
||||
ProjectFLWeight = 0.4,
|
||||
CollaborationHistoryWeight = 0.3,
|
||||
AssignedPersonnelWeight = 0.3,
|
||||
CostEfficiencyWeight = 0.4,
|
||||
LocationConvenienceWeight = 0.3,
|
||||
EmergencyResponseWeight = 0.2
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建连续性优先配置
|
||||
/// 适用场景:轮班制工作、健康管理、规律性要求高的任务
|
||||
/// </summary>
|
||||
public static OptimizationWeights CreateContinuityFirstConfiguration()
|
||||
{
|
||||
return new OptimizationWeights
|
||||
{
|
||||
ConfigurationName = "连续性优先配置",
|
||||
Description = "强调班次连续性和人员稳定性,适用于轮班制和规律性要求高的工作",
|
||||
StrategyType = OptimizationStrategy.ContinuityFirst,
|
||||
IsSystemPreset = true,
|
||||
ShiftContinuityWeight = 0.9,
|
||||
ProjectFLWeight = 0.7,
|
||||
CollaborationHistoryWeight = 0.6,
|
||||
WorkloadBalanceWeight = 0.6,
|
||||
SkillMatchWeight = 0.5,
|
||||
LocationConvenienceWeight = 0.4,
|
||||
AssignedPersonnelWeight = 0.4,
|
||||
CostEfficiencyWeight = 0.3,
|
||||
TrainingDevelopmentWeight = 0.2,
|
||||
EmergencyResponseWeight = 0.3
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 支持类定义
|
||||
|
||||
/// <summary>
|
||||
/// 优化策略类型枚举
|
||||
/// </summary>
|
||||
public enum OptimizationStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 平衡策略
|
||||
/// </summary>
|
||||
Balanced = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 效率优先
|
||||
/// </summary>
|
||||
EfficiencyFirst = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 公平分配
|
||||
/// </summary>
|
||||
FairDistribution = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 连续性优先
|
||||
/// </summary>
|
||||
ContinuityFirst = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 指定人员优先
|
||||
/// </summary>
|
||||
AssignedPersonnelFirst = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡优先
|
||||
/// </summary>
|
||||
LoadBalanceFirst = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配优先
|
||||
/// </summary>
|
||||
SkillMatchFirst = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 成本优化
|
||||
/// </summary>
|
||||
CostOptimized = 7,
|
||||
|
||||
/// <summary>
|
||||
/// 自定义策略
|
||||
/// </summary>
|
||||
Custom = 99
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权重归一化方法
|
||||
/// </summary>
|
||||
public enum WeightNormalizationMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// 不进行归一化
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 按比例归一化到总和为1
|
||||
/// </summary>
|
||||
ProportionalSum = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 按最大值归一化
|
||||
/// </summary>
|
||||
MaxValue = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 按标准差归一化
|
||||
/// </summary>
|
||||
StandardDeviation = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权重验证结果
|
||||
/// </summary>
|
||||
public class WeightValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证是否通过
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证问题列表
|
||||
/// </summary>
|
||||
public List<string> Issues { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 验证建议
|
||||
/// </summary>
|
||||
public List<string> Suggestions { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义权重规则
|
||||
/// </summary>
|
||||
public class CustomWeightRule
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则名称
|
||||
/// </summary>
|
||||
public string RuleName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 规则表达式
|
||||
/// </summary>
|
||||
public string RuleExpression { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 规则权重
|
||||
/// </summary>
|
||||
public double Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 规则描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态权重调整配置
|
||||
/// </summary>
|
||||
public class DynamicWeightAdjustment
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用动态调整
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 调整触发条件
|
||||
/// </summary>
|
||||
public List<AdjustmentTrigger> Triggers { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 调整规则
|
||||
/// </summary>
|
||||
public List<AdjustmentRule> Rules { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 最大调整幅度
|
||||
/// </summary>
|
||||
public double MaxAdjustmentRange { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 深拷贝
|
||||
/// </summary>
|
||||
public DynamicWeightAdjustment DeepClone()
|
||||
{
|
||||
return new DynamicWeightAdjustment
|
||||
{
|
||||
IsEnabled = IsEnabled,
|
||||
Triggers = new List<AdjustmentTrigger>(Triggers),
|
||||
Rules = new List<AdjustmentRule>(Rules),
|
||||
MaxAdjustmentRange = MaxAdjustmentRange
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调整触发条件
|
||||
/// </summary>
|
||||
public class AdjustmentTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发条件名称
|
||||
/// </summary>
|
||||
public string TriggerName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 触发条件表达式
|
||||
/// </summary>
|
||||
public string ConditionExpression { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 触发阈值
|
||||
/// </summary>
|
||||
public double Threshold { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调整规则
|
||||
/// </summary>
|
||||
public class AdjustmentRule
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标权重字段
|
||||
/// </summary>
|
||||
public string TargetWeightField { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 调整方式
|
||||
/// </summary>
|
||||
public AdjustmentType AdjustmentType { get; set; } = AdjustmentType.Multiply;
|
||||
|
||||
/// <summary>
|
||||
/// 调整值
|
||||
/// </summary>
|
||||
public double AdjustmentValue { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调整方式枚举
|
||||
/// </summary>
|
||||
public enum AdjustmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// 加法调整
|
||||
/// </summary>
|
||||
Add = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 乘法调整
|
||||
/// </summary>
|
||||
Multiply = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 设置固定值
|
||||
/// </summary>
|
||||
SetValue = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权重约束条件
|
||||
/// </summary>
|
||||
public class WeightConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 总权重最小值
|
||||
/// </summary>
|
||||
public double MinTotalWeight { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 总权重最大值
|
||||
/// </summary>
|
||||
public double MaxTotalWeight { get; set; } = 10.0;
|
||||
|
||||
/// <summary>
|
||||
/// 必须权重字段
|
||||
/// 这些权重字段不能为0
|
||||
/// </summary>
|
||||
public List<string> RequiredWeightFields { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 互斥权重组
|
||||
/// 同组内只能有一个权重大于指定阈值
|
||||
/// </summary>
|
||||
public List<MutuallyExclusiveWeightGroup> MutuallyExclusiveGroups { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 验证约束条件
|
||||
/// </summary>
|
||||
public WeightValidationResult ValidateConstraints(OptimizationWeights weights)
|
||||
{
|
||||
var result = new WeightValidationResult { IsValid = true, Issues = new List<string>() };
|
||||
|
||||
// 验证总权重范围
|
||||
var totalWeight = weights.GetTotalWeight();
|
||||
if (totalWeight < MinTotalWeight)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"总权重 {totalWeight:F2} 低于最小值 {MinTotalWeight:F2}");
|
||||
}
|
||||
if (totalWeight > MaxTotalWeight)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"总权重 {totalWeight:F2} 超过最大值 {MaxTotalWeight:F2}");
|
||||
}
|
||||
|
||||
// 验证必须权重字段
|
||||
var weightDict = weights.ToDictionary();
|
||||
foreach (var requiredField in RequiredWeightFields)
|
||||
{
|
||||
if (weightDict.TryGetValue(requiredField, out var value) && value <= 0)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"必须权重字段 {requiredField} 不能为0");
|
||||
}
|
||||
}
|
||||
|
||||
// 验证互斥权重组
|
||||
foreach (var group in MutuallyExclusiveGroups)
|
||||
{
|
||||
var highWeightFields = group.WeightFields
|
||||
.Where(field => weightDict.TryGetValue(field, out var value) && value > group.Threshold)
|
||||
.ToList();
|
||||
|
||||
if (highWeightFields.Count > 1)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"互斥权重组 {group.GroupName} 中有多个字段超过阈值:{string.Join(", ", highWeightFields)}");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 深拷贝
|
||||
/// </summary>
|
||||
public WeightConstraints DeepClone()
|
||||
{
|
||||
return new WeightConstraints
|
||||
{
|
||||
MinTotalWeight = MinTotalWeight,
|
||||
MaxTotalWeight = MaxTotalWeight,
|
||||
RequiredWeightFields = new List<string>(RequiredWeightFields),
|
||||
MutuallyExclusiveGroups = MutuallyExclusiveGroups.Select(g => g.DeepClone()).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 互斥权重组
|
||||
/// </summary>
|
||||
public class MutuallyExclusiveWeightGroup
|
||||
{
|
||||
/// <summary>
|
||||
/// 组名称
|
||||
/// </summary>
|
||||
public string GroupName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 权重字段列表
|
||||
/// </summary>
|
||||
public List<string> WeightFields { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 阈值
|
||||
/// </summary>
|
||||
public double Threshold { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// 深拷贝
|
||||
/// </summary>
|
||||
public MutuallyExclusiveWeightGroup DeepClone()
|
||||
{
|
||||
return new MutuallyExclusiveWeightGroup
|
||||
{
|
||||
GroupName = GroupName,
|
||||
WeightFields = new List<string>(WeightFields),
|
||||
Threshold = Threshold
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,366 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using System.Linq;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Models; // Added for .Any() and .Intersect()
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员分配推荐输入参数
|
||||
/// 用于智能推荐系统中获取最优人员分配方案的输入数据
|
||||
/// 支持多种推荐策略、批量任务处理和灵活配置选项
|
||||
/// </summary>
|
||||
public class PersonnelAllocationRecommendationInput
|
||||
{
|
||||
#region 核心任务数据
|
||||
|
||||
/// <summary>
|
||||
/// 工作任务ID列表
|
||||
/// 需要推荐人员分配的具体工作任务
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "工作任务ID列表不能为空")]
|
||||
[MinLength(1, ErrorMessage = "至少需要一个工作任务")]
|
||||
public List<long> WorkOrderIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 推荐策略
|
||||
/// 控制推荐算法的优先级和侧重点
|
||||
/// </summary>
|
||||
public PersonnelAllocationStrategy Strategy { get; set; } = PersonnelAllocationStrategy.FairDistribution;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 推荐配置选项
|
||||
|
||||
/// <summary>
|
||||
/// 每个任务的推荐人数
|
||||
/// 为每个任务推荐的前N个候选人员数量
|
||||
/// </summary>
|
||||
[Range(1, 10, ErrorMessage = "推荐人数应在1-10之间")]
|
||||
public int RecommendationCount { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含详细评分
|
||||
/// 在推荐结果中包含各维度的详细评分信息
|
||||
/// </summary>
|
||||
public bool IncludeDetailedScores { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含风险评估
|
||||
/// 在推荐结果中包含潜在风险和冲突检测
|
||||
/// </summary>
|
||||
public bool IncludeRiskAssessment { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含替代方案
|
||||
/// 当最优方案不可行时,提供替代分配方案
|
||||
/// </summary>
|
||||
public bool IncludeAlternativeSolutions { get; set; } = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 筛选和约束条件
|
||||
|
||||
/// <summary>
|
||||
/// 排除的人员ID列表
|
||||
/// 明确指定不参与推荐的人员
|
||||
/// </summary>
|
||||
public List<long> ExcludedPersonnelIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 优先考虑的人员ID列表
|
||||
/// 在同等条件下优先推荐的人员
|
||||
/// </summary>
|
||||
public List<long> PreferredPersonnelIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 最小资质匹配度要求 (0-100)
|
||||
/// 推荐人员必须达到的最低资质匹配分数
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "最小资质匹配度应在0-100之间")]
|
||||
public double MinimumQualificationScore { get; set; } = 60.0;
|
||||
|
||||
/// <summary>
|
||||
/// 最小约束符合度要求 (0-100)
|
||||
/// 推荐人员必须达到的最低约束符合分数
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "最小约束符合度应在0-100之间")]
|
||||
public double MinimumConstraintScore { get; set; } = 60.0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 时间范围控制
|
||||
|
||||
/// <summary>
|
||||
/// 推荐基准日期
|
||||
/// 作为推荐计算的基准时间点
|
||||
/// </summary>
|
||||
public DateTime RecommendationBaseDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 推荐时间范围
|
||||
/// 限制推荐计算的时间窗口
|
||||
/// </summary>
|
||||
public DateRange? TimeRange { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务上下文信息
|
||||
|
||||
/// <summary>
|
||||
/// 推荐请求来源
|
||||
/// 标识推荐触发的业务场景
|
||||
/// </summary>
|
||||
public RecommendationSource RequestSource { get; set; } = RecommendationSource.Manual;
|
||||
|
||||
/// <summary>
|
||||
/// 操作员信息
|
||||
/// 记录执行推荐的用户
|
||||
/// </summary>
|
||||
public OperatorInfo Operator { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 推荐批次标识
|
||||
/// 用于关联和追踪推荐过程
|
||||
/// </summary>
|
||||
public string RecommendationBatchId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 业务场景标识
|
||||
/// 标识具体的业务使用场景
|
||||
/// </summary>
|
||||
public string BusinessScenario { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 优先级权重配置
|
||||
/// 自定义各评分维度的权重分配
|
||||
/// </summary>
|
||||
public Dictionary<string, double> CustomWeights { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 性能和质量控制
|
||||
|
||||
/// <summary>
|
||||
/// 推荐超时时间(秒)
|
||||
/// 防止推荐过程过长影响用户体验
|
||||
/// </summary>
|
||||
[Range(5, 300, ErrorMessage = "推荐超时时间应在5-300秒之间")]
|
||||
public int RecommendationTimeoutSeconds { get; set; } = 60;
|
||||
|
||||
/// <summary>
|
||||
/// 最小推荐置信度 (0-100)
|
||||
/// 只返回置信度达到此阈值的推荐结果
|
||||
/// </summary>
|
||||
[Range(0, 100, ErrorMessage = "最小推荐置信度应在0-100之间")]
|
||||
public double MinimumConfidenceLevel { get; set; } = 70.0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用缓存
|
||||
/// 使用缓存提高推荐性能
|
||||
/// </summary>
|
||||
public bool EnableCaching { get; set; } = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 高级配置选项
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡策略
|
||||
/// 控制推荐时的人员工作负载分配策略
|
||||
/// </summary>
|
||||
public LoadBalanceStrategy LoadBalanceStrategy { get; set; } = LoadBalanceStrategy.Moderate;
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配策略
|
||||
/// 控制技能匹配的严格程度
|
||||
/// </summary>
|
||||
public SkillMatchStrategy SkillMatchStrategy { get; set; } = SkillMatchStrategy.Balanced;
|
||||
|
||||
/// <summary>
|
||||
/// 历史表现权重
|
||||
/// 历史工作表现对推荐的影响权重
|
||||
/// </summary>
|
||||
[Range(0, 1, ErrorMessage = "历史表现权重应在0-1之间")]
|
||||
public double HistoricalPerformanceWeight { get; set; } = 0.3;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 验证和约束
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用严格验证
|
||||
/// 启用更严格的推荐结果验证
|
||||
/// </summary>
|
||||
public bool EnableStrictValidation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含合规性检查
|
||||
/// 在推荐中包含法规和制度合规性检查
|
||||
/// </summary>
|
||||
public bool IncludeComplianceCheck { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含成本效益分析
|
||||
/// 在推荐中包含成本效益评估
|
||||
/// </summary>
|
||||
public bool IncludeCostBenefitAnalysis { get; set; } = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 输出格式控制
|
||||
|
||||
/// <summary>
|
||||
/// 输出语言
|
||||
/// 推荐结果的显示语言
|
||||
/// </summary>
|
||||
public string OutputLanguage { get; set; } = "zh-CN";
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含可视化数据
|
||||
/// 在结果中包含图表和可视化所需的数据
|
||||
/// </summary>
|
||||
public bool IncludeVisualizationData { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含执行建议
|
||||
/// 在结果中包含具体的执行建议和注意事项
|
||||
/// </summary>
|
||||
public bool IncludeExecutionAdvice { get; set; } = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
public PersonnelAllocationRecommendationInput()
|
||||
{
|
||||
// 设置默认值
|
||||
WorkOrderIds = new List<long>();
|
||||
ExcludedPersonnelIds = new List<long>();
|
||||
PreferredPersonnelIds = new List<long>();
|
||||
CustomWeights = new Dictionary<string, double>();
|
||||
TimeRange = null;
|
||||
}
|
||||
|
||||
public PersonnelAllocationRecommendationInput(List<long> workOrderIds, PersonnelAllocationStrategy strategy = PersonnelAllocationStrategy.FairDistribution)
|
||||
{
|
||||
WorkOrderIds = workOrderIds ?? new List<long>();
|
||||
Strategy = strategy;
|
||||
ExcludedPersonnelIds = new List<long>();
|
||||
PreferredPersonnelIds = new List<long>();
|
||||
CustomWeights = new Dictionary<string, double>();
|
||||
TimeRange = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 相关枚举定义
|
||||
|
||||
/// <summary>
|
||||
/// 推荐请求来源
|
||||
/// </summary>
|
||||
public enum RecommendationSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动触发
|
||||
/// </summary>
|
||||
Manual = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 系统自动
|
||||
/// </summary>
|
||||
System = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 定时任务
|
||||
/// </summary>
|
||||
Scheduled = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 外部接口
|
||||
/// </summary>
|
||||
External = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 工作流触发
|
||||
/// </summary>
|
||||
Workflow = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡策略
|
||||
/// </summary>
|
||||
public enum LoadBalanceStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 保守策略
|
||||
/// 优先考虑人员休息和负载均衡
|
||||
/// </summary>
|
||||
Conservative = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 平衡策略
|
||||
/// 平衡效率和负载均衡
|
||||
/// </summary>
|
||||
Moderate = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 激进策略
|
||||
/// 优先考虑任务完成效率
|
||||
/// </summary>
|
||||
Aggressive = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配策略
|
||||
/// </summary>
|
||||
public enum SkillMatchStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 严格匹配
|
||||
/// 要求技能完全匹配
|
||||
/// </summary>
|
||||
Strict = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 平衡匹配
|
||||
/// 允许部分技能匹配,考虑学习能力
|
||||
/// </summary>
|
||||
Balanced = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 宽松匹配
|
||||
/// 允许技能相近,优先考虑人员发展
|
||||
/// </summary>
|
||||
Flexible = 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助类
|
||||
|
||||
/// <summary>
|
||||
/// 日期范围
|
||||
/// </summary>
|
||||
public class DateRange
|
||||
{
|
||||
/// <summary>
|
||||
/// 开始日期
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束日期
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间范围跨度
|
||||
/// </summary>
|
||||
public TimeSpan Duration => EndDate - StartDate;
|
||||
}
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,613 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员分配验证输入
|
||||
/// 用于智能分配系统中验证人员分配方案的可行性和合规性
|
||||
/// 支持批量验证、多维度检查和灵活配置
|
||||
/// </summary>
|
||||
public class PersonnelAllocationValidationInput
|
||||
{
|
||||
#region 核心验证数据
|
||||
|
||||
/// <summary>
|
||||
/// 待验证的人员分配列表
|
||||
/// 包含任务与人员的具体分配关系
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "人员分配列表不能为空")]
|
||||
[MinLength(1, ErrorMessage = "至少需要一个分配项")]
|
||||
public List<PersonnelAssignment> Assignments { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 验证配置选项
|
||||
|
||||
/// <summary>
|
||||
/// 验证级别
|
||||
/// 控制验证的严格程度和覆盖范围
|
||||
/// </summary>
|
||||
public ValidationLevel ValidationLevel { get; set; } = ValidationLevel.Standard;
|
||||
|
||||
/// <summary>
|
||||
/// 验证范围配置
|
||||
/// 可选择验证的具体维度
|
||||
/// </summary>
|
||||
public ValidationScopeConfig ValidationScope { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含冲突检测
|
||||
/// 检测分配间的相互冲突
|
||||
/// </summary>
|
||||
public bool IncludeConflictDetection { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含性能分析
|
||||
/// 分析验证对系统性能的影响
|
||||
/// </summary>
|
||||
public bool IncludePerformanceAnalysis { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 验证超时时间(秒)
|
||||
/// 防止验证过程过长影响用户体验
|
||||
/// </summary>
|
||||
[Range(5, 300, ErrorMessage = "验证超时时间应在5-300秒之间")]
|
||||
public int ValidationTimeoutSeconds { get; set; } = 30;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务上下文信息
|
||||
|
||||
/// <summary>
|
||||
/// 验证请求来源
|
||||
/// 标识验证触发的业务场景
|
||||
/// </summary>
|
||||
public ValidationSource RequestSource { get; set; } = ValidationSource.Manual;
|
||||
|
||||
/// <summary>
|
||||
/// 操作员信息
|
||||
/// 记录执行验证的用户
|
||||
/// </summary>
|
||||
public OperatorInfo Operator { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 验证批次标识
|
||||
/// 用于关联和追踪验证过程
|
||||
/// </summary>
|
||||
public string ValidationBatchId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 业务场景标识
|
||||
/// 标识具体的业务使用场景
|
||||
/// </summary>
|
||||
public string BusinessScenario { get; set; } = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 时间范围控制
|
||||
|
||||
/// <summary>
|
||||
/// 验证基准日期
|
||||
/// 作为验证计算的基准时间点
|
||||
/// </summary>
|
||||
public DateTime ValidationBaseDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 验证时间范围
|
||||
/// 限制验证的时间窗口
|
||||
/// </summary>
|
||||
public DateTimeRange ValidationTimeRange { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否忽略历史数据
|
||||
/// 是否跳过已过时的分配验证
|
||||
/// </summary>
|
||||
public bool IgnoreHistoricalData { get; set; } = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 自定义验证规则
|
||||
|
||||
/// <summary>
|
||||
/// 自定义验证规则列表
|
||||
/// 支持业务特定的验证逻辑
|
||||
/// </summary>
|
||||
public List<CustomValidationRule> CustomRules { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 验证权重配置
|
||||
/// 各类验证项的重要性权重
|
||||
/// </summary>
|
||||
public ValidationWeights Weights { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 排除验证的项目
|
||||
/// 明确不需要验证的特定项目
|
||||
/// </summary>
|
||||
public List<string> ExcludedValidationTypes { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
/// <summary>
|
||||
/// 验证输入数据的完整性
|
||||
/// </summary>
|
||||
public ValidationInputCheckResult ValidateInput()
|
||||
{
|
||||
var result = new ValidationInputCheckResult { IsValid = true, Issues = new List<string>() };
|
||||
|
||||
// 基础数据验证
|
||||
if (!Assignments.Any())
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add("分配列表不能为空");
|
||||
}
|
||||
|
||||
// 分配数据完整性检查
|
||||
foreach (var assignment in Assignments)
|
||||
{
|
||||
if (assignment.WorkOrderId <= 0)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"无效的工作任务ID: {assignment.WorkOrderId}");
|
||||
}
|
||||
|
||||
if (assignment.PersonnelId <= 0)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"无效的人员ID: {assignment.PersonnelId}");
|
||||
}
|
||||
|
||||
if (assignment.AssignmentDate == default)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add($"任务ID {assignment.WorkOrderId} 的分配日期无效");
|
||||
}
|
||||
}
|
||||
|
||||
// 时间范围合理性检查
|
||||
if (ValidationTimeRange.IsValid() && ValidationTimeRange.EndDate < ValidationTimeRange.StartDate)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add("验证时间范围配置错误");
|
||||
}
|
||||
|
||||
// 超时时间合理性检查
|
||||
if (ValidationTimeoutSeconds < 5 || ValidationTimeoutSeconds > 300)
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Issues.Add("验证超时时间配置超出有效范围");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证统计信息
|
||||
/// </summary>
|
||||
public ValidationInputStatistics GetStatistics()
|
||||
{
|
||||
return new ValidationInputStatistics
|
||||
{
|
||||
TotalAssignments = Assignments.Count,
|
||||
UniquePersonnelCount = Assignments.Select(a => a.PersonnelId).Distinct().Count(),
|
||||
UniqueTaskCount = Assignments.Select(a => a.WorkOrderId).Distinct().Count(),
|
||||
DateRangeSpan = Assignments.Any()
|
||||
? (Assignments.Max(a => a.AssignmentDate) - Assignments.Min(a => a.AssignmentDate)).Days
|
||||
: 0,
|
||||
ValidationScopeCount = ValidationScope.GetEnabledScopeCount(),
|
||||
CustomRuleCount = CustomRules.Count,
|
||||
EstimatedExecutionTimeSeconds = EstimateExecutionTime()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 估算验证执行时间
|
||||
/// </summary>
|
||||
private int EstimateExecutionTime()
|
||||
{
|
||||
// 基础验证时间(每个分配项约0.1秒)
|
||||
var baseTime = Assignments.Count * 0.1;
|
||||
|
||||
// 冲突检测额外时间
|
||||
if (IncludeConflictDetection)
|
||||
baseTime += Assignments.Count * 0.05;
|
||||
|
||||
// 性能分析额外时间
|
||||
if (IncludePerformanceAnalysis)
|
||||
baseTime += 2;
|
||||
|
||||
// 自定义规则额外时间
|
||||
baseTime += CustomRules.Count * 0.2;
|
||||
|
||||
return Math.Max(1, (int)Math.Ceiling(baseTime));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 支持类定义
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配项
|
||||
/// 定义具体的任务-人员分配关系
|
||||
/// </summary>
|
||||
public class PersonnelAssignment
|
||||
{
|
||||
/// <summary>
|
||||
/// 工作任务ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "工作任务ID必须大于0")]
|
||||
public long WorkOrderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "人员ID必须大于0")]
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配日期
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime AssignmentDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 班次ID
|
||||
/// </summary>
|
||||
public long? ShiftId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预计工作小时数
|
||||
/// </summary>
|
||||
[Range(0.1, 24, ErrorMessage = "预计工作小时数应在0.1-24之间")]
|
||||
public decimal EstimatedWorkHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配优先级
|
||||
/// 用于冲突时的优先级判断
|
||||
/// </summary>
|
||||
[Range(1, 10, ErrorMessage = "优先级应在1-10之间")]
|
||||
public int Priority { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 分配标签
|
||||
/// 用于分类和筛选
|
||||
/// </summary>
|
||||
public List<string> Tags { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 备注信息
|
||||
/// </summary>
|
||||
[MaxLength(500, ErrorMessage = "备注信息不能超过500字符")]
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为强制分配
|
||||
/// 强制分配将跳过某些验证规则
|
||||
/// </summary>
|
||||
public bool IsMandatoryAssignment { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证级别枚举
|
||||
/// </summary>
|
||||
public enum ValidationLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础验证 - 仅检查最基本的约束
|
||||
/// </summary>
|
||||
Basic = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 标准验证 - 包含常用的验证规则
|
||||
/// </summary>
|
||||
Standard = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 严格验证 - 全面的验证检查
|
||||
/// </summary>
|
||||
Strict = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 自定义验证 - 根据配置执行验证
|
||||
/// </summary>
|
||||
Custom = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证范围配置
|
||||
/// 控制具体验证的维度
|
||||
/// </summary>
|
||||
public class ValidationScopeConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证资质匹配
|
||||
/// </summary>
|
||||
public bool ValidateQualification { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 验证时间冲突
|
||||
/// </summary>
|
||||
public bool ValidateTimeConflict { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 验证工作限制
|
||||
/// </summary>
|
||||
public bool ValidateWorkLimit { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 验证班次规则
|
||||
/// </summary>
|
||||
public bool ValidateShiftRule { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 验证负载均衡
|
||||
/// </summary>
|
||||
public bool ValidateLoadBalance { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 验证技能匹配
|
||||
/// </summary>
|
||||
public bool ValidateSkillMatch { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 验证成本控制
|
||||
/// </summary>
|
||||
public bool ValidateCostControl { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 获取启用的验证范围数量
|
||||
/// </summary>
|
||||
public int GetEnabledScopeCount()
|
||||
{
|
||||
int count = 0;
|
||||
if (ValidateQualification) count++;
|
||||
if (ValidateTimeConflict) count++;
|
||||
if (ValidateWorkLimit) count++;
|
||||
if (ValidateShiftRule) count++;
|
||||
if (ValidateLoadBalance) count++;
|
||||
if (ValidateSkillMatch) count++;
|
||||
if (ValidateCostControl) count++;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证来源枚举
|
||||
/// </summary>
|
||||
public enum ValidationSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动验证
|
||||
/// </summary>
|
||||
Manual = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 自动验证
|
||||
/// </summary>
|
||||
Automatic = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 批量验证
|
||||
/// </summary>
|
||||
Batch = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 定时验证
|
||||
/// </summary>
|
||||
Scheduled = 4,
|
||||
|
||||
/// <summary>
|
||||
/// API调用验证
|
||||
/// </summary>
|
||||
ApiCall = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作员信息
|
||||
/// </summary>
|
||||
public class OperatorInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作员ID
|
||||
/// </summary>
|
||||
public long OperatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员姓名
|
||||
/// </summary>
|
||||
public string OperatorName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作时间
|
||||
/// </summary>
|
||||
public DateTime OperationTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 操作IP地址
|
||||
/// </summary>
|
||||
public string IpAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作角色
|
||||
/// </summary>
|
||||
public string Role { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日期时间范围
|
||||
/// </summary>
|
||||
public class DateTimeRange
|
||||
{
|
||||
/// <summary>
|
||||
/// 开始时间
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束时间
|
||||
/// </summary>
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为有效的时间范围
|
||||
/// </summary>
|
||||
public bool IsValid()
|
||||
{
|
||||
return StartDate != default && EndDate != default && StartDate <= EndDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取时间跨度(天数)
|
||||
/// </summary>
|
||||
public int GetDaySpan()
|
||||
{
|
||||
return IsValid() ? (EndDate - StartDate).Days : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义验证规则
|
||||
/// </summary>
|
||||
public class CustomValidationRule
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则ID
|
||||
/// </summary>
|
||||
public string RuleId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 规则名称
|
||||
/// </summary>
|
||||
public string RuleName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 规则类型
|
||||
/// </summary>
|
||||
public string RuleType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 规则配置参数
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Parameters { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 规则权重
|
||||
/// </summary>
|
||||
[Range(0.1, 10.0, ErrorMessage = "规则权重应在0.1-10.0之间")]
|
||||
public double Weight { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证权重配置
|
||||
/// </summary>
|
||||
public class ValidationWeights
|
||||
{
|
||||
/// <summary>
|
||||
/// 资质验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double QualificationWeight { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 时间冲突验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double TimeConflictWeight { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 工作限制验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double WorkLimitWeight { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double ShiftRuleWeight { get; set; } = 0.8;
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double LoadBalanceWeight { get; set; } = 0.6;
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配验证权重
|
||||
/// </summary>
|
||||
[Range(0.0, 10.0)]
|
||||
public double SkillMatchWeight { get; set; } = 0.7;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证输入检查结果
|
||||
/// </summary>
|
||||
public class ValidationInputCheckResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 输入是否有效
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 问题列表
|
||||
/// </summary>
|
||||
public List<string> Issues { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证输入统计信息
|
||||
/// </summary>
|
||||
public class ValidationInputStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// 总分配数量
|
||||
/// </summary>
|
||||
public int TotalAssignments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一人员数量
|
||||
/// </summary>
|
||||
public int UniquePersonnelCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一任务数量
|
||||
/// </summary>
|
||||
public int UniqueTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日期范围跨度(天)
|
||||
/// </summary>
|
||||
public int DateRangeSpan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证范围数量
|
||||
/// </summary>
|
||||
public int ValidationScopeCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义规则数量
|
||||
/// </summary>
|
||||
public int CustomRuleCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预估执行时间(秒)
|
||||
/// </summary>
|
||||
public int EstimatedExecutionTimeSeconds { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,424 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理任务变更输入
|
||||
/// 用于检测和处理发布后的任务变更,触发智能重新分配
|
||||
/// </summary>
|
||||
public class ProcessTaskChangesInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 变更的任务ID列表
|
||||
/// 指定需要处理变更的任务
|
||||
/// </summary>
|
||||
public List<long> ChangedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// 指定要更新的整合记录
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更触发源
|
||||
/// TaskModification-任务修改, ResourceUnavailable-资源不可用, ConflictDetected-冲突检测, UserRequest-用户请求
|
||||
/// </summary>
|
||||
public string ChangeTriggerSource { get; set; } = "TaskModification";
|
||||
|
||||
/// <summary>
|
||||
/// 处理策略
|
||||
/// AutoReallocation-自动重新分配, ManualReview-手动审核, CreateNewVersion-创建新版本
|
||||
/// </summary>
|
||||
public string ProcessingStrategy { get; set; } = "AutoReallocation";
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户ID
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户名
|
||||
/// </summary>
|
||||
public string OperatorUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作员真实姓名
|
||||
/// </summary>
|
||||
public string OperatorRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更原因说明
|
||||
/// </summary>
|
||||
public string ChangeReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制重新分配
|
||||
/// 即使影响评分较低也强制执行重新分配
|
||||
/// </summary>
|
||||
public bool ForceReallocation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否保持现有分配
|
||||
/// 尽量保持当前的人员和设备分配,只调整有问题的部分
|
||||
/// </summary>
|
||||
public bool PreserveExistingAllocations { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 重新分配范围
|
||||
/// ChangedOnly-仅重新分配变更的任务, Affected-重新分配受影响的任务, All-重新分配所有任务
|
||||
/// </summary>
|
||||
public string ReallocationScope { get; set; } = "Affected";
|
||||
|
||||
/// <summary>
|
||||
/// 优先级调整策略
|
||||
/// None-不调整, Boost-提升变更任务优先级, Balance-平衡所有任务优先级
|
||||
/// </summary>
|
||||
public string PriorityAdjustmentStrategy { get; set; } = "None";
|
||||
|
||||
/// <summary>
|
||||
/// 通知相关人员
|
||||
/// 变更处理完成后是否通知受影响的人员
|
||||
/// </summary>
|
||||
public bool NotifyAffectedPersonnel { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 创建变更日志
|
||||
/// 是否详细记录变更处理过程
|
||||
/// </summary>
|
||||
public bool CreateChangeLog { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 允许的最大处理时间(分钟)
|
||||
/// 超时则转为手动处理
|
||||
/// </summary>
|
||||
public int MaxProcessingTimeMinutes { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// 业务备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分析深度
|
||||
/// 指定变更分析的深度级别
|
||||
/// </summary>
|
||||
public TaskChangeAnalysisDepth AnalysisDepth { get; set; } = TaskChangeAnalysisDepth.Standard;
|
||||
|
||||
/// <summary>
|
||||
/// 版本创建原因
|
||||
/// 当处理策略为CreateNewVersion时使用
|
||||
/// </summary>
|
||||
public string VersionReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否发送通知
|
||||
/// 处理完成后是否发送通知给相关人员
|
||||
/// </summary>
|
||||
public bool SendNotifications { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 智能重新分配输入
|
||||
/// 用于触发智能重新分配算法
|
||||
/// </summary>
|
||||
public class SmartReallocationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录ID(根版本ID)
|
||||
/// </summary>
|
||||
public long RootIntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 需要重新分配的任务ID列表
|
||||
/// 为空则表示重新分配所有任务
|
||||
/// </summary>
|
||||
public List<long> TaskIdsToReallocate { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 重新分配策略配置
|
||||
/// 可以重用原策略或指定新策略
|
||||
/// </summary>
|
||||
public SmartReallocationStrategyConfig Strategy { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 约束条件
|
||||
/// 指定重新分配时需要遵守的约束条件
|
||||
/// </summary>
|
||||
public List<ReallocationConstraint> Constraints { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户ID
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员用户名
|
||||
/// </summary>
|
||||
public string OperatorUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 操作员真实姓名
|
||||
/// </summary>
|
||||
public string OperatorRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 重新分配原因
|
||||
/// </summary>
|
||||
public string ReallocationReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否创建新版本
|
||||
/// true-创建新版本保留历史, false-更新当前版本
|
||||
/// </summary>
|
||||
public bool CreateNewVersion { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 预期完成时间
|
||||
/// 指定重新分配的预期完成时间
|
||||
/// </summary>
|
||||
public DateTime? ExpectedCompletionTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 质量优先级
|
||||
/// 分配时的质量要求优先级:Low, Medium, High, Critical
|
||||
/// </summary>
|
||||
public string QualityPriority { get; set; } = "Medium";
|
||||
|
||||
/// <summary>
|
||||
/// 成本控制要求
|
||||
/// 是否需要考虑成本控制
|
||||
/// </summary>
|
||||
public bool ConsiderCostControl { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 最大成本预算
|
||||
/// </summary>
|
||||
public decimal? MaxBudget { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// 相关的整合记录标识
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更的任务ID列表
|
||||
/// 需要进行重新分配的任务
|
||||
/// </summary>
|
||||
public List<long> ChangedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 版本创建原因
|
||||
/// 重新分配时创建版本的原因说明
|
||||
/// </summary>
|
||||
public string VersionReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 受影响的任务ID列表
|
||||
/// 可能受到变更影响的任务
|
||||
/// </summary>
|
||||
public List<long> AffectedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否重新分配人员
|
||||
/// </summary>
|
||||
public bool ReallocatePersonnel { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否重新分配设备
|
||||
/// </summary>
|
||||
public bool ReallocateEquipment { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 智能重新分配策略配置
|
||||
/// </summary>
|
||||
public class SmartReallocationStrategyConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否使用原策略
|
||||
/// </summary>
|
||||
public bool UseOriginalStrategy { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配策略
|
||||
/// </summary>
|
||||
public string PersonnelStrategy { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配策略
|
||||
/// </summary>
|
||||
public string EquipmentStrategy { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 强制执行班次规则
|
||||
/// </summary>
|
||||
public bool EnforceShiftRules { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 优化目标
|
||||
/// Efficiency-效率优先, Fairness-公平优先, Balance-平衡, Quality-质量优先
|
||||
/// </summary>
|
||||
public string OptimizationTarget { get; set; } = "Balance";
|
||||
|
||||
/// <summary>
|
||||
/// 变更影响最小化
|
||||
/// 尽量减少对现有分配的影响
|
||||
/// </summary>
|
||||
public bool MinimizeChangeImpact { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 允许跨班次调整
|
||||
/// </summary>
|
||||
public bool AllowCrossShiftAdjustment { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 允许跨项目资源共享
|
||||
/// </summary>
|
||||
public bool AllowCrossProjectSharing { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 高级配置参数
|
||||
/// </summary>
|
||||
public Dictionary<string, object> AdvancedSettings { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新分配约束条件
|
||||
/// </summary>
|
||||
public class ReallocationConstraint
|
||||
{
|
||||
/// <summary>
|
||||
/// 约束类型
|
||||
/// Personnel-人员约束, Equipment-设备约束, Time-时间约束, Cost-成本约束
|
||||
/// </summary>
|
||||
public string ConstraintType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 约束目标ID
|
||||
/// 人员ID、设备ID等
|
||||
/// </summary>
|
||||
public long? TargetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 约束操作
|
||||
/// MustInclude-必须包含, MustExclude-必须排除, Prefer-优先选择, Avoid-尽量避免
|
||||
/// </summary>
|
||||
public string ConstraintOperation { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 约束值
|
||||
/// 具体的约束值或条件
|
||||
/// </summary>
|
||||
public string ConstraintValue { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 约束优先级
|
||||
/// 1-9,9为最高优先级
|
||||
/// </summary>
|
||||
public int Priority { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 约束说明
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为硬约束
|
||||
/// true-硬约束(必须满足), false-软约束(尽量满足)
|
||||
/// </summary>
|
||||
public bool IsHardConstraint { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 版本历史查询输入
|
||||
/// </summary>
|
||||
public class IntegrationVersionHistoryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 根版本ID
|
||||
/// </summary>
|
||||
public long RootVersionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 需要比较的版本ID列表
|
||||
/// </summary>
|
||||
public List<long> CompareVersionIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 查询开始时间
|
||||
/// </summary>
|
||||
public DateTime? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询结束时间
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本状态过滤
|
||||
/// Active-活跃版本, Inactive-非活跃版本, All-所有版本
|
||||
/// </summary>
|
||||
public string VersionStatusFilter { get; set; } = "All";
|
||||
|
||||
/// <summary>
|
||||
/// 变更类型过滤
|
||||
/// </summary>
|
||||
public List<string> ChangeTypeFilter { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 操作员过滤
|
||||
/// </summary>
|
||||
public List<long> OperatorFilter { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含快照数据
|
||||
/// </summary>
|
||||
public bool IncludeSnapshotData { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含变更详情
|
||||
/// </summary>
|
||||
public bool IncludeChangeDetails { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 页码
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 页大小
|
||||
/// </summary>
|
||||
public int PageSize { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// 排序字段
|
||||
/// CreatedTime, Version, ImpactScore
|
||||
/// </summary>
|
||||
public string SortBy { get; set; } = "CreatedTime";
|
||||
|
||||
/// <summary>
|
||||
/// 排序方向
|
||||
/// Asc, Desc
|
||||
/// </summary>
|
||||
public string SortDirection { get; set; } = "Desc";
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含性能指标
|
||||
/// </summary>
|
||||
public bool IncludePerformanceMetrics { get; set; } = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
|
||||
/// <summary>
|
||||
/// 发布整合记录输入参数
|
||||
/// 包含发布操作的所有必要信息和业务规则验证参数
|
||||
///
|
||||
/// 业务思考:
|
||||
/// 1. 发布是整合记录生命周期的关键节点,需要严格的权限验证
|
||||
/// 2. 发布后任务状态将从PendingIntegration更新为Assigned,这是不可逆操作
|
||||
/// 3. 支持发布备注,记录发布的业务背景和特殊说明
|
||||
/// 4. 包含强制发布选项,应对特殊业务场景但需要额外权限
|
||||
/// </summary>
|
||||
public class PublishIntegrationRecordInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "整合记录ID不能为空")]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "整合记录ID必须大于0")]
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员用户ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "发布操作员用户ID不能为空")]
|
||||
[Range(1, long.MaxValue, ErrorMessage = "发布操作员用户ID必须大于0")]
|
||||
public long PublishedByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员用户名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "发布操作员用户名不能为空")]
|
||||
[StringLength(50, ErrorMessage = "发布操作员用户名长度不能超过50个字符")]
|
||||
public string PublishedByUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发布操作员真实姓名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "发布操作员真实姓名不能为空")]
|
||||
[StringLength(50, ErrorMessage = "发布操作员真实姓名长度不能超过50个字符")]
|
||||
public string PublishedByRealName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发布说明
|
||||
/// 记录发布的业务背景、特殊情况或注意事项
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "发布说明长度不能超过500个字符")]
|
||||
public string PublishRemarks { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否跳过发布前验证
|
||||
/// 默认false,true时需要额外权限验证
|
||||
///
|
||||
/// 业务意义:
|
||||
/// - 正常情况应该为false,进行完整的发布前验证
|
||||
/// - 紧急情况下可以设为true,但需要管理员权限
|
||||
/// - 跳过验证的发布需要记录审计日志
|
||||
/// </summary>
|
||||
public bool SkipPrePublishValidation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制发布
|
||||
/// 当发现潜在冲突但仍需要发布时使用,需要特殊权限
|
||||
///
|
||||
/// 业务场景:
|
||||
/// - 临时调整导致的轻微冲突但业务必须继续
|
||||
/// - 系统维护期间的特殊发布需求
|
||||
/// - 应急处理场景下的破例发布
|
||||
/// </summary>
|
||||
public bool ForcePublish { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 预期发布生效时间
|
||||
/// null表示立即生效,否则按指定时间生效
|
||||
///
|
||||
/// 业务考虑:
|
||||
/// - 支持定时发布功能,便于计划性任务安排
|
||||
/// - 立即发布适用于紧急任务调度
|
||||
/// - 定时发布可以配合班次计划进行优化
|
||||
/// </summary>
|
||||
public DateTime? ScheduledPublishTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布后是否自动开始任务
|
||||
/// 控制发布后是否将任务状态进一步更新为InProgress
|
||||
///
|
||||
/// 业务逻辑:
|
||||
/// - true:发布后任务自动开始执行(PendingIntegration -> Assigned -> InProgress)
|
||||
/// - false:发布后任务处于已分配状态,等待手动开始(PendingIntegration -> Assigned)
|
||||
/// </summary>
|
||||
public bool AutoStartTasksAfterPublish { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 通知相关人员
|
||||
/// 发布后是否通知相关的人员和设备管理员
|
||||
/// </summary>
|
||||
public bool NotifyRelatedPersonnel { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 发布范围限制
|
||||
/// 指定只发布特定任务,null表示发布整合记录中的所有任务
|
||||
///
|
||||
/// 业务价值:
|
||||
/// - 支持部分发布功能,提高发布的灵活性
|
||||
/// - 当某些任务出现问题时,可以单独发布其他正常任务
|
||||
/// - 便于分阶段发布和风险控制
|
||||
/// </summary>
|
||||
public List<long>? SpecificTaskIds { get; set; }
|
||||
}
|
@ -0,0 +1,292 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// 智能整合输入
|
||||
/// </summary>
|
||||
public class SmartIntegrationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 选中的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> SelectedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 选中的项目号列表
|
||||
/// </summary>
|
||||
public List<string> SelectedProjectNumbers { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 整合策略配置
|
||||
/// </summary>
|
||||
public IntegrationStrategy Strategy { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 操作员信息
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
public string OperatorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合批次名称(可选)
|
||||
/// </summary>
|
||||
public string BatchName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合策略
|
||||
/// </summary>
|
||||
public class IntegrationStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员分配策略
|
||||
/// </summary>
|
||||
public PersonnelAllocationStrategy PersonnelStrategy { get; set; } = PersonnelAllocationStrategy.FairDistribution;
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配策略
|
||||
/// </summary>
|
||||
public EquipmentAllocationStrategy EquipmentStrategy { get; set; } = EquipmentAllocationStrategy.MaxUtilization;
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制满足班次规则
|
||||
/// </summary>
|
||||
public bool EnforceShiftRules { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否优先分配高优先级任务
|
||||
/// </summary>
|
||||
public bool PrioritizeHighPriorityTasks { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否考虑人员资质匹配
|
||||
/// </summary>
|
||||
public bool ConsiderQualificationMatch { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用负载均衡
|
||||
/// </summary>
|
||||
public bool EnableLoadBalancing { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 最大连续工作天数限制
|
||||
/// </summary>
|
||||
public int? MaxContinuousWorkDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备利用率目标(百分比)
|
||||
/// </summary>
|
||||
public decimal TargetEquipmentUtilization { get; set; } = 80.0m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配策略枚举
|
||||
/// </summary>
|
||||
public enum PersonnelAllocationStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 公平分配(均衡工作量)
|
||||
/// </summary>
|
||||
FairDistribution = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 技能优先(优先匹配最佳技能)
|
||||
/// </summary>
|
||||
SkillPriority = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 效率优先(优先分配给高效人员)
|
||||
/// </summary>
|
||||
EfficiencyPriority = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡(平衡所有人员工作负荷)
|
||||
/// </summary>
|
||||
LoadBalance = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配策略枚举
|
||||
/// </summary>
|
||||
public enum EquipmentAllocationStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大利用率(优先使用利用率高的设备)
|
||||
/// </summary>
|
||||
MaxUtilization = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡(平衡所有设备使用率)
|
||||
/// </summary>
|
||||
LoadBalance = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 性能优先(优先使用性能最佳的设备)
|
||||
/// </summary>
|
||||
PerformancePriority = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 就近分配(优先分配距离最近的设备)
|
||||
/// </summary>
|
||||
ProximityPriority = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配输入
|
||||
/// 深度架构思考:支持两种输入模式,避免重复数据库查询,提升性能和数据一致性
|
||||
/// </summary>
|
||||
public class PersonnelAllocationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 待分配的任务ID列表(当Tasks为空时使用)
|
||||
/// </summary>
|
||||
public List<long> TaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 待分配的任务对象列表(性能优化:避免重复数据库查询)
|
||||
/// 深度业务考量:当上级调用方已经加载了完整的task对象时,直接传入可以:
|
||||
/// 1. 避免重复数据库查询,提升性能
|
||||
/// 2. 确保数据一致性,防止查询间隙的数据变更
|
||||
/// 3. 减少Include操作的开销
|
||||
/// 使用优先级:Tasks > TaskIds
|
||||
/// </summary>
|
||||
public List<WorkOrderEntity> Tasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配策略
|
||||
/// </summary>
|
||||
public PersonnelAllocationStrategy Strategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否强制满足班次规则
|
||||
/// </summary>
|
||||
public bool EnforceShiftRules { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 排除的人员ID列表(不参与分配)
|
||||
/// </summary>
|
||||
public List<long> ExcludedPersonnelIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 优先考虑的人员ID列表
|
||||
/// </summary>
|
||||
public List<long> PreferredPersonnelIds { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配输入
|
||||
/// 深度架构优化:支持两种输入模式,避免重复数据库查询,提升性能和数据一致性
|
||||
/// </summary>
|
||||
public class EquipmentAllocationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 待分配的任务ID列表(当Tasks为空时使用)
|
||||
/// </summary>
|
||||
public List<long> TaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 待分配的任务对象列表(性能优化:避免重复数据库查询)
|
||||
/// 深度业务考量:当上级调用方(SmartScheduleOrchestratorService)已经加载了完整的task对象时,直接传入可以:
|
||||
/// 1. 避免重复数据库查询,提升性能50%以上
|
||||
/// 2. 确保数据一致性,防止查询间隙的数据变更
|
||||
/// 3. 减少Include操作的开销,降低内存占用
|
||||
/// 4. 保持与PersonnelAllocationInput相同的优化模式
|
||||
/// 使用优先级:Tasks > TaskIds
|
||||
/// </summary>
|
||||
public List<WorkOrderEntity> Tasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配策略
|
||||
/// </summary>
|
||||
public EquipmentAllocationStrategy Strategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标利用率(百分比)
|
||||
/// </summary>
|
||||
public decimal TargetUtilization { get; set; } = 80.0m;
|
||||
|
||||
/// <summary>
|
||||
/// 排除的设备ID列表(不参与分配)
|
||||
/// </summary>
|
||||
public List<long> ExcludedEquipmentIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 优先考虑的设备ID列表
|
||||
/// </summary>
|
||||
public List<long> PreferredEquipmentIds { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录输入
|
||||
/// </summary>
|
||||
public class IntegrationRecordInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合的任务ID列表
|
||||
/// </summary>
|
||||
public List<long> TaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 人员分配结果
|
||||
/// </summary>
|
||||
public PersonnelAllocationResult PersonnelAllocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备分配结果
|
||||
/// </summary>
|
||||
public EquipmentAllocationResult EquipmentAllocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合策略
|
||||
/// </summary>
|
||||
public IntegrationStrategy Strategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员信息
|
||||
/// </summary>
|
||||
public long OperatorUserId { get; set; }
|
||||
public string OperatorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合备注
|
||||
/// </summary>
|
||||
public string Remarks { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整合历史查询输入
|
||||
/// </summary>
|
||||
public class IntegrationHistoryQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作员ID
|
||||
/// </summary>
|
||||
public long? OperatorUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目号
|
||||
/// </summary>
|
||||
public string ProjectNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合时间范围
|
||||
/// </summary>
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分页参数
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 20;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// 最终业务规则验证结果
|
||||
/// 业务用途:对遗传算法输出进行严格的业务规则二次验证的结果
|
||||
/// </summary>
|
||||
public class FinalValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否通过验证
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误消息
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规详情列表
|
||||
/// </summary>
|
||||
public List<GlobalConflictDetectionInfo> Violations { get; set; } = new List<GlobalConflictDetectionInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 验证的任务数量
|
||||
/// </summary>
|
||||
public int ValidatedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检测到的违规数量
|
||||
/// </summary>
|
||||
public int ViolationCount => Violations.Count;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
|
||||
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Models;
|
||||
|
||||
public class AllocationContext
|
||||
{
|
||||
public AllocationContext()
|
||||
{
|
||||
// 初始化所有集合属性,避免空引用异常
|
||||
WorkOrders = new List<WorkOrderEntity>();
|
||||
WeightConfiguration = new Dictionary<string, double>();
|
||||
AvailablePersonnel = new List<PersonnelEntity>();
|
||||
ProcessingLog = new List<string>();
|
||||
Errors = new List<string>();
|
||||
ConstraintResults = new Dictionary<long, List<ConstraintEvaluationResult>>();
|
||||
FilteredCandidates = new Dictionary<long, List<PersonnelCandidate>>();
|
||||
Metrics = new Dictionary<string, object>();
|
||||
OptimizationResults = new Dictionary<long, List<OptimizationScoreResult>>();
|
||||
}
|
||||
|
||||
public string ContextId { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public List<WorkOrderEntity> WorkOrders { get; set; }
|
||||
|
||||
public PersonnelAllocationStrategy Strategy { get; set; }
|
||||
|
||||
public Dictionary<string, double> WeightConfiguration { get; set; }
|
||||
|
||||
public List<PersonnelEntity> AvailablePersonnel { get; set; }
|
||||
|
||||
public List<string> ProcessingLog { get; set; }
|
||||
|
||||
public List<string> Errors { get; set; }
|
||||
|
||||
public Dictionary<long, List<ConstraintEvaluationResult>> ConstraintResults { get; set; }
|
||||
|
||||
public Dictionary<long, List<PersonnelCandidate>> FilteredCandidates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 性能指标字典
|
||||
/// 存储分配过程中各阶段的性能数据,如执行时间、处理数量等
|
||||
/// Key: 指标名称,Value: 指标值
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Metrics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 优化决策结果字典
|
||||
/// 存储每个工作任务的优化决策详细结果
|
||||
/// Key: 工作任务ID, Value: 优化评分结果列表
|
||||
/// </summary>
|
||||
public Dictionary<long, List<OptimizationScoreResult>> OptimizationResults { get; set; }
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员工作负载分析
|
||||
/// 用于智能分配算法中的人员工作量评估和负载均衡
|
||||
/// </summary>
|
||||
public class PersonnelWorkloadAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员姓名
|
||||
/// </summary>
|
||||
public string PersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 已分配任务数量
|
||||
/// </summary>
|
||||
public int AssignedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计划工作小时数
|
||||
/// </summary>
|
||||
public decimal ScheduledWorkHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作负载百分比 (0-100)
|
||||
/// 相对于标准工作量的百分比
|
||||
/// </summary>
|
||||
public double WorkloadPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 负载状态描述
|
||||
/// </summary>
|
||||
public string WorkloadStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否超负荷
|
||||
/// </summary>
|
||||
public bool IsOverloaded => WorkloadPercentage > 100;
|
||||
|
||||
/// <summary>
|
||||
/// 剩余可分配容量
|
||||
/// </summary>
|
||||
public decimal RemainingCapacity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配度平均分
|
||||
/// </summary>
|
||||
public decimal AverageSkillMatchScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分配的任务列表
|
||||
/// </summary>
|
||||
public List<AssignedTaskInfo> AssignedTasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 工作时间段分布
|
||||
/// Key: 日期, Value: 工作小时数
|
||||
/// </summary>
|
||||
public Dictionary<DateTime, decimal> DailyWorkHoursDistribution { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡评分 (0-100)
|
||||
/// 评估当前负载是否合理均衡
|
||||
/// </summary>
|
||||
public int LoadBalanceScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新时间
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; } = DateTime.Now;
|
||||
|
||||
public List<DateTime> WorkDates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计算连续工作天数
|
||||
/// </summary>
|
||||
public int ContinuousWorkDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总工时
|
||||
/// </summary>
|
||||
public decimal? TotalEstimatedHours { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已分配任务信息
|
||||
/// </summary>
|
||||
public class AssignedTaskInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务编码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 预计工作小时数
|
||||
/// </summary>
|
||||
public decimal EstimatedWorkHours { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务优先级
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计划开始时间
|
||||
/// </summary>
|
||||
public DateTime ScheduledStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计划结束时间
|
||||
/// </summary>
|
||||
public DateTime ScheduledEndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 技能匹配度
|
||||
/// </summary>
|
||||
public decimal SkillMatchScore { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,852 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证违规信息
|
||||
/// 通用的验证违规模型,用于各类验证场景
|
||||
/// </summary>
|
||||
public class ValidationViolation
|
||||
{
|
||||
/// <summary>
|
||||
/// 违规ID
|
||||
/// </summary>
|
||||
public string ViolationId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 违规类型
|
||||
/// </summary>
|
||||
public string ViolationType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规严重程度
|
||||
/// </summary>
|
||||
public ViolationSeverity Severity { get; set; } = ViolationSeverity.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// 相关实体ID
|
||||
/// </summary>
|
||||
public long EntityId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 相关实体类型
|
||||
/// </summary>
|
||||
public string EntityType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规详细信息
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Details { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 建议解决方案
|
||||
/// </summary>
|
||||
public List<string> SuggestedSolutions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 发现时间
|
||||
/// </summary>
|
||||
public DateTime DetectedAt { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为阻塞性问题
|
||||
/// </summary>
|
||||
public bool IsBlockingIssue { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 业务影响度 (1-10)
|
||||
/// </summary>
|
||||
public int BusinessImpact { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 违规分类
|
||||
/// </summary>
|
||||
public ViolationCategory Category { get; set; } = ViolationCategory.General;
|
||||
|
||||
/// <summary>
|
||||
/// 是否可通过审批强制执行
|
||||
/// </summary>
|
||||
public bool CanOverrideWithApproval { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 所需审批级别
|
||||
/// </summary>
|
||||
public ApprovalLevel RequiredApprovalLevel { get; set; } = ApprovalLevel.None;
|
||||
|
||||
/// <summary>
|
||||
/// 违规风险评估
|
||||
/// </summary>
|
||||
public ViolationRiskAssessment RiskAssessment { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证警告信息
|
||||
/// 通用的验证警告模型,用于各类验证场景
|
||||
/// </summary>
|
||||
public class ValidationWarning
|
||||
{
|
||||
/// <summary>
|
||||
/// 警告ID
|
||||
/// </summary>
|
||||
public string WarningId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 警告类型
|
||||
/// </summary>
|
||||
public string WarningType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 警告消息
|
||||
/// </summary>
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 警告级别
|
||||
/// </summary>
|
||||
public WarningLevel Level { get; set; } = WarningLevel.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// 相关实体ID
|
||||
/// </summary>
|
||||
public long EntityId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 相关实体类型
|
||||
/// </summary>
|
||||
public string EntityType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 建议关注程度 (1-10)
|
||||
/// </summary>
|
||||
public int AttentionLevel { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 相关任务ID列表
|
||||
/// </summary>
|
||||
public List<long> RelatedTaskIds { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 建议操作
|
||||
/// </summary>
|
||||
public string SuggestedAction { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发现时间
|
||||
/// </summary>
|
||||
public DateTime DetectedAt { get; set; } = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 约束违规信息
|
||||
/// 专门用于约束评估过程中的违规记录,比通用违规类更轻量
|
||||
/// </summary>
|
||||
public class ConstraintViolation
|
||||
{
|
||||
/// <summary>
|
||||
/// 违规ID
|
||||
/// </summary>
|
||||
public string ViolationId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 违规类型
|
||||
/// </summary>
|
||||
public string ViolationType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 违规严重程度
|
||||
/// </summary>
|
||||
public ViolationSeverity Severity { get; set; } = ViolationSeverity.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// 违规详细信息
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Details { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 发现时间
|
||||
/// </summary>
|
||||
public DateTime DetectedAt { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为阻塞性问题
|
||||
/// </summary>
|
||||
public bool IsBlockingIssue { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 业务影响度 (1-10)
|
||||
/// </summary>
|
||||
public int BusinessImpact { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 违规分类
|
||||
/// </summary>
|
||||
public ViolationCategory Category { get; set; } = ViolationCategory.General;
|
||||
|
||||
/// <summary>
|
||||
/// 是否可通过审批强制执行
|
||||
/// </summary>
|
||||
public bool CanOverrideWithApproval { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 所需审批级别
|
||||
/// </summary>
|
||||
public ApprovalLevel RequiredApprovalLevel { get; set; } = ApprovalLevel.None;
|
||||
|
||||
/// <summary>
|
||||
/// 建议解决方案
|
||||
/// </summary>
|
||||
public List<string> SuggestedSolutions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 违规风险评估
|
||||
/// </summary>
|
||||
public ViolationRiskAssessment RiskAssessment { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 创建新的约束违规实例
|
||||
/// </summary>
|
||||
public static ConstraintViolation Create(string violationType, string description, ViolationSeverity severity = ViolationSeverity.Medium)
|
||||
{
|
||||
return new ConstraintViolation
|
||||
{
|
||||
ViolationType = violationType,
|
||||
Description = description,
|
||||
Severity = severity,
|
||||
DetectedAt = DateTime.Now
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建阻塞性违规
|
||||
/// </summary>
|
||||
public static ConstraintViolation CreateBlocking(string violationType, string description, ViolationSeverity severity = ViolationSeverity.High)
|
||||
{
|
||||
return new ConstraintViolation
|
||||
{
|
||||
ViolationType = violationType,
|
||||
Description = description,
|
||||
Severity = severity,
|
||||
IsBlockingIssue = true,
|
||||
DetectedAt = DateTime.Now
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 违规类型枚举
|
||||
/// 定义人员分配过程中可能出现的各种违规类型
|
||||
/// </summary>
|
||||
public enum ViolationType
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用违规
|
||||
/// </summary>
|
||||
General = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 资质不匹配
|
||||
/// 业务场景:人员资质与任务要求不符
|
||||
/// </summary>
|
||||
QualificationMismatch = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 时间冲突
|
||||
/// 业务场景:人员在同一时间段被分配多个任务
|
||||
/// </summary>
|
||||
TimeConflict = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 工作量超限
|
||||
/// 业务场景:人员工作负载超过限制
|
||||
/// </summary>
|
||||
WorkloadExceeded = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则冲突
|
||||
/// 业务场景:违反班次连续性、同天班次等规则
|
||||
/// </summary>
|
||||
ShiftRuleViolation = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 工作限制违规
|
||||
/// 业务场景:违反连续工作天数、周班次数等限制
|
||||
/// </summary>
|
||||
WorkLimitViolation = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态违规
|
||||
/// 业务场景:人员状态异常、系统配置问题等
|
||||
/// </summary>
|
||||
SystemStateViolation = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 业务规则冲突
|
||||
/// 业务场景:违反项目特定规则、部门限制等
|
||||
/// </summary>
|
||||
BusinessRuleViolation = 7
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 违规严重程度枚举
|
||||
/// 定义违规的严重程度级别,用于决策和审批流程
|
||||
/// </summary>
|
||||
public enum ViolationSeverity
|
||||
{
|
||||
/// <summary>
|
||||
/// 信息级 - 纯信息提示,不影响分配
|
||||
/// 业务场景:建议性信息、优化提示、统计数据
|
||||
/// 处理方式:记录但不影响分配决策
|
||||
/// </summary>
|
||||
Info = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 低级 - 轻微问题,可接受
|
||||
/// 业务场景:次优选择、轻微偏好违背、资源利用率稍低
|
||||
/// 处理方式:允许分配,但降低优先级
|
||||
/// </summary>
|
||||
Low = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 警告级 - 需要关注但不阻止
|
||||
/// 业务场景:连续工作天数较多、工作负载偏高、非首选班次
|
||||
/// 处理方式:允许分配,但给出明确警告
|
||||
/// </summary>
|
||||
Warning = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 中级 - 需要关注的问题
|
||||
/// 业务场景:技能匹配度不理想、班次连续性问题、资源冲突风险
|
||||
/// 处理方式:默认阻止分配,可通过管理员审批
|
||||
/// </summary>
|
||||
Medium = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 高级 - 重要问题,建议阻止
|
||||
/// 业务场景:工作限制超出、重要资质缺失、严重时间冲突
|
||||
/// 处理方式:强烈建议阻止,需要高级权限审批
|
||||
/// </summary>
|
||||
High = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 错误级 - 业务规则违反,必须处理
|
||||
/// 业务场景:违反硬性约束、安全规定冲突、合规性问题
|
||||
/// 处理方式:阻止分配,必须修复后重试
|
||||
/// </summary>
|
||||
Error = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 严重级 - 系统级问题,完全阻止
|
||||
/// 业务场景:数据完整性问题、系统状态异常、关键资源不可用
|
||||
/// 处理方式:完全阻止分配,需要系统级修复
|
||||
/// </summary>
|
||||
Critical = 6
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 警告级别枚举
|
||||
/// </summary>
|
||||
public enum WarningLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 低级警告
|
||||
/// </summary>
|
||||
Low = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 中级警告
|
||||
/// </summary>
|
||||
Medium = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 高级警告
|
||||
/// </summary>
|
||||
High = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 违规分类枚举
|
||||
/// </summary>
|
||||
public enum ViolationCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用违规
|
||||
/// </summary>
|
||||
General = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 资质相关违规
|
||||
/// </summary>
|
||||
Qualification = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 时间冲突违规
|
||||
/// </summary>
|
||||
TimeConflict = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 工作限制违规
|
||||
/// </summary>
|
||||
WorkLimit = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 班次规则违规
|
||||
/// </summary>
|
||||
ShiftRule = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 业务规则违规
|
||||
/// </summary>
|
||||
BusinessRule = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 安全规定违规
|
||||
/// </summary>
|
||||
Safety = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 合规性违规
|
||||
/// </summary>
|
||||
Compliance = 7,
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态违规
|
||||
/// </summary>
|
||||
SystemState = 8
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 审批级别枚举
|
||||
/// </summary>
|
||||
public enum ApprovalLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 无需审批
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 自动审批
|
||||
/// </summary>
|
||||
Automatic = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 主管审批
|
||||
/// </summary>
|
||||
Supervisor = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 管理员审批
|
||||
/// </summary>
|
||||
Manager = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 高级管理员审批
|
||||
/// </summary>
|
||||
SeniorManager = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 系统管理员审批
|
||||
/// </summary>
|
||||
SystemAdmin = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 违规风险评估
|
||||
/// </summary>
|
||||
public class ViolationRiskAssessment
|
||||
{
|
||||
/// <summary>
|
||||
/// 安全风险等级 (1-10)
|
||||
/// </summary>
|
||||
public int SafetyRiskLevel { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 合规风险等级 (1-10)
|
||||
/// </summary>
|
||||
public int ComplianceRiskLevel { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 运营风险等级 (1-10)
|
||||
/// </summary>
|
||||
public int OperationalRiskLevel { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 财务风险等级 (1-10)
|
||||
/// </summary>
|
||||
public int FinancialRiskLevel { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 综合风险评分 (1-10)
|
||||
/// </summary>
|
||||
public double OverallRiskScore => (SafetyRiskLevel + ComplianceRiskLevel + OperationalRiskLevel + FinancialRiskLevel) / 4.0;
|
||||
|
||||
/// <summary>
|
||||
/// 风险描述
|
||||
/// </summary>
|
||||
public string RiskDescription { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 缓解措施建议
|
||||
/// </summary>
|
||||
public List<string> MitigationSuggestions { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 违规严重程度判定辅助类
|
||||
/// 智能排班系统违规严重程度业务逻辑判定器
|
||||
/// 深度业务思考:根据不同业务场景智能判定违规的真实严重程度和处理方式
|
||||
/// </summary>
|
||||
public static class ViolationSeverityJudge
|
||||
{
|
||||
/// <summary>
|
||||
/// 判定是否为阻塞性违规
|
||||
/// 深度业务思考:根据严重程度和业务影响综合判断是否应该阻止分配
|
||||
/// </summary>
|
||||
public static bool IsBlockingViolation(ViolationSeverity severity, int businessImpact = 5, ViolationCategory category = ViolationCategory.General)
|
||||
{
|
||||
// 信息级和低级违规不阻塞
|
||||
if (severity <= ViolationSeverity.Low) return false;
|
||||
|
||||
// 警告级违规根据业务影响和分类判断
|
||||
if (severity == ViolationSeverity.Warning)
|
||||
{
|
||||
// 安全和合规相关的警告需要阻塞
|
||||
if (category == ViolationCategory.Safety || category == ViolationCategory.Compliance)
|
||||
return businessImpact >= 7;
|
||||
|
||||
// 其他警告不阻塞
|
||||
return false;
|
||||
}
|
||||
|
||||
// 中级违规根据分类判断
|
||||
if (severity == ViolationSeverity.Medium)
|
||||
{
|
||||
// 资质和安全相关的中级违规需要阻塞
|
||||
return category == ViolationCategory.Qualification ||
|
||||
category == ViolationCategory.Safety ||
|
||||
category == ViolationCategory.Compliance;
|
||||
}
|
||||
|
||||
// 高级及以上违规都需要阻塞
|
||||
return severity >= ViolationSeverity.High;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算违规失败阈值
|
||||
/// 深度业务思考:不同业务场景下的违规容忍度不同
|
||||
/// </summary>
|
||||
public static ViolationSeverity GetFailureThreshold(ValidationContext context)
|
||||
{
|
||||
// 紧急情况下提高容忍度
|
||||
if (context.IsEmergencyMode)
|
||||
return ViolationSeverity.Error;
|
||||
|
||||
// 关键任务降低容忍度
|
||||
if (context.IsCriticalTask)
|
||||
return ViolationSeverity.Medium;
|
||||
|
||||
// 安全相关任务严格控制
|
||||
if (context.IsSafetyRelated)
|
||||
return ViolationSeverity.Warning;
|
||||
|
||||
// 默认阈值:高级违规
|
||||
return ViolationSeverity.High;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所需审批级别
|
||||
/// </summary>
|
||||
public static ApprovalLevel GetRequiredApprovalLevel(ViolationSeverity severity, ViolationCategory category)
|
||||
{
|
||||
return (severity, category) switch
|
||||
{
|
||||
(ViolationSeverity.Info or ViolationSeverity.Low, _) => ApprovalLevel.None,
|
||||
(ViolationSeverity.Warning, ViolationCategory.Safety or ViolationCategory.Compliance) => ApprovalLevel.Supervisor,
|
||||
(ViolationSeverity.Warning, _) => ApprovalLevel.Automatic,
|
||||
(ViolationSeverity.Medium, ViolationCategory.Safety) => ApprovalLevel.Manager,
|
||||
(ViolationSeverity.Medium, _) => ApprovalLevel.Supervisor,
|
||||
(ViolationSeverity.High, ViolationCategory.Safety or ViolationCategory.Compliance) => ApprovalLevel.SeniorManager,
|
||||
(ViolationSeverity.High, _) => ApprovalLevel.Manager,
|
||||
(ViolationSeverity.Error, ViolationCategory.SystemState) => ApprovalLevel.SystemAdmin,
|
||||
(ViolationSeverity.Error, _) => ApprovalLevel.SeniorManager,
|
||||
(ViolationSeverity.Critical, _) => ApprovalLevel.SystemAdmin,
|
||||
_ => ApprovalLevel.None
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以通过审批强制执行
|
||||
/// </summary>
|
||||
public static bool CanOverrideWithApproval(ViolationSeverity severity, ViolationCategory category)
|
||||
{
|
||||
// 系统状态和关键安全违规不能强制执行
|
||||
if (category == ViolationCategory.SystemState && severity >= ViolationSeverity.Error)
|
||||
return false;
|
||||
|
||||
if (category == ViolationCategory.Safety && severity >= ViolationSeverity.Critical)
|
||||
return false;
|
||||
|
||||
// 严重级系统违规不能强制执行
|
||||
if (severity == ViolationSeverity.Critical &&
|
||||
(category == ViolationCategory.SystemState || category == ViolationCategory.Compliance))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算违规权重
|
||||
/// 用于验证评分计算
|
||||
/// </summary>
|
||||
public static double GetViolationWeight(ViolationSeverity severity)
|
||||
{
|
||||
return severity switch
|
||||
{
|
||||
ViolationSeverity.Info => 0.5,
|
||||
ViolationSeverity.Low => 1.0,
|
||||
ViolationSeverity.Warning => 2.0,
|
||||
ViolationSeverity.Medium => 5.0,
|
||||
ViolationSeverity.High => 10.0,
|
||||
ViolationSeverity.Error => 20.0,
|
||||
ViolationSeverity.Critical => 50.0,
|
||||
_ => 1.0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证上下文
|
||||
/// 用于判定违规严重程度的业务上下文
|
||||
/// </summary>
|
||||
public class ValidationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为紧急模式
|
||||
/// </summary>
|
||||
public bool IsEmergencyMode { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为关键任务
|
||||
/// </summary>
|
||||
public bool IsCriticalTask { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否与安全相关
|
||||
/// </summary>
|
||||
public bool IsSafetyRelated { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 业务优先级 (1-10)
|
||||
/// </summary>
|
||||
public int BusinessPriority { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 验证模式
|
||||
/// </summary>
|
||||
public ValidationMode Mode { get; set; } = ValidationMode.Standard;
|
||||
|
||||
/// <summary>
|
||||
/// 额外上下文信息
|
||||
/// </summary>
|
||||
public Dictionary<string, object> AdditionalContext { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证模式枚举
|
||||
/// </summary>
|
||||
public enum ValidationMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 标准验证
|
||||
/// </summary>
|
||||
Standard = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 严格验证
|
||||
/// </summary>
|
||||
Strict = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 宽松验证
|
||||
/// </summary>
|
||||
Lenient = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 紧急验证
|
||||
/// </summary>
|
||||
Emergency = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 优化评分结果
|
||||
/// 用于记录人员分配优化过程中的各项评分和决策信息
|
||||
/// </summary>
|
||||
public class OptimizationScoreResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 候选人信息
|
||||
/// </summary>
|
||||
public object Candidate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 各维度评分
|
||||
/// </summary>
|
||||
public Dictionary<string, double> DimensionScores { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 优化总分
|
||||
/// </summary>
|
||||
public double OptimizationScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 置信度
|
||||
/// </summary>
|
||||
public double Confidence { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 推荐等级
|
||||
/// </summary>
|
||||
public RecommendationLevel RecommendationLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 优化理由
|
||||
/// </summary>
|
||||
public string OptimizationReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 风险评估
|
||||
/// </summary>
|
||||
public RiskAssessment RiskAssessment { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 推荐等级枚举
|
||||
/// </summary>
|
||||
public enum RecommendationLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// 强烈推荐
|
||||
/// </summary>
|
||||
HighlyRecommended = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 推荐
|
||||
/// </summary>
|
||||
Recommended = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 可接受
|
||||
/// </summary>
|
||||
Acceptable = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 不推荐
|
||||
/// </summary>
|
||||
NotRecommended = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 不可行
|
||||
/// </summary>
|
||||
NotFeasible = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 风险评估
|
||||
/// </summary>
|
||||
public class RiskAssessment
|
||||
{
|
||||
/// <summary>
|
||||
/// 风险因子列表
|
||||
/// </summary>
|
||||
public List<RiskFactor> RiskFactors { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 总体风险等级
|
||||
/// </summary>
|
||||
public RiskLevel OverallRiskLevel { get; set; } = RiskLevel.Low;
|
||||
|
||||
/// <summary>
|
||||
/// 风险评分
|
||||
/// </summary>
|
||||
public double RiskScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 风险描述
|
||||
/// </summary>
|
||||
public string RiskDescription { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 缓解建议
|
||||
/// </summary>
|
||||
public List<string> MitigationSuggestions { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 风险因子
|
||||
/// </summary>
|
||||
public class RiskFactor
|
||||
{
|
||||
/// <summary>
|
||||
/// 风险类型
|
||||
/// </summary>
|
||||
public string RiskType { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 风险描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 风险等级
|
||||
/// </summary>
|
||||
public RiskLevel Level { get; set; } = RiskLevel.Low;
|
||||
|
||||
/// <summary>
|
||||
/// 发生概率 (0-100)
|
||||
/// </summary>
|
||||
public double Probability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 影响程度 (0-100)
|
||||
/// </summary>
|
||||
public double Impact { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 决策评分
|
||||
/// </summary>
|
||||
public class DecisionScore
|
||||
{
|
||||
/// <summary>
|
||||
/// 最终评分
|
||||
/// </summary>
|
||||
public double FinalScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 置信度
|
||||
/// </summary>
|
||||
public double ConfidenceLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 风险等级
|
||||
/// </summary>
|
||||
public RiskLevel RiskLevel { get; set; } = RiskLevel.Low;
|
||||
|
||||
/// <summary>
|
||||
/// 决策理由
|
||||
/// </summary>
|
||||
public string DecisionReason { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,324 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Time.Output;
|
||||
using NPP.SmartSchedue.Api.Contracts.Services.Work.Output;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销整合记录结果
|
||||
/// 包含撤销操作的详细结果和状态信息
|
||||
/// </summary>
|
||||
public class CancelIntegrationRecordResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 撤销是否成功
|
||||
/// </summary>
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销成功消息
|
||||
/// </summary>
|
||||
public string SuccessMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销失败消息
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销时间
|
||||
/// </summary>
|
||||
public DateTime CancelledTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销的批次编码
|
||||
/// </summary>
|
||||
public string IntegrationBatchCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 成功撤销的任务详情
|
||||
/// </summary>
|
||||
public List<CancelledTaskDetail> CancelledTasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 撤销失败的任务详情
|
||||
/// </summary>
|
||||
public List<FailedCancelTaskDetail> FailedCancelTasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态回滚结果
|
||||
/// </summary>
|
||||
public TaskStatusRollbackResult TaskStatusRollbackResult { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前验证结果
|
||||
/// </summary>
|
||||
public CancelValidationResult ValidationResult { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 通知发送结果
|
||||
/// </summary>
|
||||
public List<NotificationSendResult> NotificationResults { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 撤销统计信息
|
||||
/// </summary>
|
||||
public CancelStatistics Statistics { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 警告信息列表
|
||||
/// </summary>
|
||||
public List<string> WarningMessages { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已撤销任务详情
|
||||
/// </summary>
|
||||
public class CancelledTaskDetail
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前分配的人员ID
|
||||
/// </summary>
|
||||
public long? PreviousAssignedPersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前分配的人员姓名
|
||||
/// </summary>
|
||||
public string PreviousAssignedPersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前分配的设备ID
|
||||
/// </summary>
|
||||
public long? PreviousAssignedEquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前分配的设备名称
|
||||
/// </summary>
|
||||
public string PreviousAssignedEquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销前状态
|
||||
/// </summary>
|
||||
public string PreviousStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 撤销后状态
|
||||
/// </summary>
|
||||
public string CurrentStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务撤销时间
|
||||
/// </summary>
|
||||
public DateTime CancelTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销失败任务详情
|
||||
/// </summary>
|
||||
public class FailedCancelTaskDetail
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 失败原因
|
||||
/// </summary>
|
||||
public string FailureReason { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 详细错误信息
|
||||
/// </summary>
|
||||
public List<string> DetailedErrors { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 解决建议
|
||||
/// </summary>
|
||||
public List<string> Suggestions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务状态
|
||||
/// </summary>
|
||||
public string CurrentTaskStatus { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态回滚结果
|
||||
/// </summary>
|
||||
public class TaskStatusRollbackResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 回滚是否完全成功
|
||||
/// </summary>
|
||||
public bool IsFullySuccessful { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功回滚的任务数量
|
||||
/// </summary>
|
||||
public int SuccessfulRollbackCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 回滚失败的任务数量
|
||||
/// </summary>
|
||||
public int FailedRollbackCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 回滚详细结果
|
||||
/// </summary>
|
||||
public List<TaskRollbackDetail> RollbackDetails { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 回滚耗时(毫秒)
|
||||
/// </summary>
|
||||
public long RollbackElapsedMilliseconds { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务回滚详情
|
||||
/// </summary>
|
||||
public class TaskRollbackDetail
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 回滚是否成功
|
||||
/// </summary>
|
||||
public bool IsRollbackSuccessful { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原始状态
|
||||
/// </summary>
|
||||
public string OriginalStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 目标状态
|
||||
/// </summary>
|
||||
public string TargetStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 实际状态
|
||||
/// </summary>
|
||||
public string ActualStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 回滚错误信息
|
||||
/// </summary>
|
||||
public string RollbackError { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 回滚时间
|
||||
/// </summary>
|
||||
public DateTime RollbackTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销验证结果
|
||||
/// </summary>
|
||||
public class CancelValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证是否通过
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证执行时间
|
||||
/// </summary>
|
||||
public DateTime ValidationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阻塞性错误(会阻止撤销)
|
||||
/// </summary>
|
||||
public List<IntegrationValidationError> BlockingErrors { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 警告性问题(不阻止撤销但需要注意)
|
||||
/// </summary>
|
||||
public List<ValidationWarning> Warnings { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 验证详情
|
||||
/// </summary>
|
||||
public string ValidationDetails { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发现的进行中任务数量
|
||||
/// </summary>
|
||||
public int InProgressTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 需要强制撤销的任务列表
|
||||
/// </summary>
|
||||
public List<long> TasksRequiringForceCancel { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 撤销统计信息
|
||||
/// </summary>
|
||||
public class CancelStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// 总任务数
|
||||
/// </summary>
|
||||
public int TotalTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成功撤销任务数
|
||||
/// </summary>
|
||||
public int SuccessfulCancelCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销失败任务数
|
||||
/// </summary>
|
||||
public int FailedCancelCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 涉及人员数量
|
||||
/// </summary>
|
||||
public int InvolvedPersonnelCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 涉及设备数量
|
||||
/// </summary>
|
||||
public int InvolvedEquipmentCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销成功率
|
||||
/// </summary>
|
||||
public decimal CancelSuccessRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤销总耗时(毫秒)
|
||||
/// </summary>
|
||||
public long TotalElapsedMilliseconds { get; set; }
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
|
||||
|
||||
/// <summary>
|
||||
/// 完成整合记录结果
|
||||
/// 包含完成操作的详细结果和统计信息
|
||||
/// </summary>
|
||||
public class CompleteIntegrationRecordResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 完成操作是否成功
|
||||
/// </summary>
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成成功消息
|
||||
/// </summary>
|
||||
public string SuccessMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 完成失败消息
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 整合记录ID
|
||||
/// </summary>
|
||||
public long IntegrationRecordId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成时间
|
||||
/// </summary>
|
||||
public DateTime CompletedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 整合批次编码
|
||||
/// </summary>
|
||||
public string IntegrationBatchCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 完成验证结果
|
||||
/// 验证所有任务是否都已完成
|
||||
/// </summary>
|
||||
public CompleteValidationResult ValidationResult { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 完成统计信息
|
||||
/// </summary>
|
||||
public CompleteStatistics Statistics { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 警告信息列表
|
||||
/// </summary>
|
||||
public List<string> WarningMessages { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 完成验证结果
|
||||
/// </summary>
|
||||
public class CompleteValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证是否通过
|
||||
/// </summary>
|
||||
public bool IsValid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证时间
|
||||
/// </summary>
|
||||
public DateTime ValidationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总任务数
|
||||
/// </summary>
|
||||
public int TotalTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已完成任务数
|
||||
/// </summary>
|
||||
public int CompletedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 未完成任务数
|
||||
/// </summary>
|
||||
public int IncompleteTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 未完成任务列表
|
||||
/// </summary>
|
||||
public List<IncompleteTaskInfo> IncompleteTasks { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 完成率
|
||||
/// </summary>
|
||||
public decimal CompletionRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证详情
|
||||
/// </summary>
|
||||
public string ValidationDetails { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未完成任务信息
|
||||
/// </summary>
|
||||
public class IncompleteTaskInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务代码
|
||||
/// </summary>
|
||||
public string TaskCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public string CurrentStatus { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配人员姓名
|
||||
/// </summary>
|
||||
public string AssignedPersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 分配设备名称
|
||||
/// </summary>
|
||||
public string AssignedEquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 计划工作日期
|
||||
/// </summary>
|
||||
public DateTime WorkOrderDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 未完成原因
|
||||
/// </summary>
|
||||
public string IncompleteReason { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 完成统计信息
|
||||
/// </summary>
|
||||
public class CompleteStatistics
|
||||
{
|
||||
/// <summary>
|
||||
/// 整合记录持续时间(从发布到完成的毫秒数)
|
||||
/// </summary>
|
||||
public long IntegrationDurationMilliseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均任务执行时间(毫秒)
|
||||
/// </summary>
|
||||
public long AverageTaskExecutionTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最快完成任务时间(毫秒)
|
||||
/// </summary>
|
||||
public long FastestTaskTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最慢完成任务时间(毫秒)
|
||||
/// </summary>
|
||||
public long SlowestTaskTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员效率统计
|
||||
/// </summary>
|
||||
public List<PersonnelEfficiencyStats> PersonnelEfficiencyStats { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 设备利用率统计
|
||||
/// </summary>
|
||||
public List<EquipmentUtilizationStats> EquipmentUtilizationStats { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 整体效率评分(0-100)
|
||||
/// </summary>
|
||||
public int OverallEfficiencyScore { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 人员效率统计
|
||||
/// </summary>
|
||||
public class PersonnelEfficiencyStats
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员ID
|
||||
/// </summary>
|
||||
public long PersonnelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员姓名
|
||||
/// </summary>
|
||||
public string PersonnelName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 完成任务数
|
||||
/// </summary>
|
||||
public int CompletedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平均任务耗时(毫秒)
|
||||
/// </summary>
|
||||
public long AverageTaskTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 效率评分(0-100)
|
||||
/// </summary>
|
||||
public int EfficiencyScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务质量评分(0-100)
|
||||
/// </summary>
|
||||
public int QualityScore { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备利用率统计
|
||||
/// </summary>
|
||||
public class EquipmentUtilizationStats
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public long EquipmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
public string EquipmentName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 完成任务数
|
||||
/// </summary>
|
||||
public int CompletedTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总使用时间(毫秒)
|
||||
/// </summary>
|
||||
public long TotalUsageTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际利用率(百分比)
|
||||
/// </summary>
|
||||
public decimal ActualUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 计划利用率(百分比)
|
||||
/// </summary>
|
||||
public decimal PlannedUtilizationRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 利用率达成度(百分比)
|
||||
/// </summary>
|
||||
public decimal UtilizationAchievementRate { get; set; }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user