diff --git a/QcMgr/Tnb.QcMgr.Entities/Dto/SpcData.cs b/QcMgr/Tnb.QcMgr.Entities/Dto/SpcData.cs
index 705cfb5a..e5af3a8a 100644
--- a/QcMgr/Tnb.QcMgr.Entities/Dto/SpcData.cs
+++ b/QcMgr/Tnb.QcMgr.Entities/Dto/SpcData.cs
@@ -3,10 +3,108 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Spire.Xls.Core.Spreadsheet.Charts;
namespace Tnb.QcMgr.Entities
{
public class SpcDataInput
{
+ ///
+ /// 主表id
+ ///
+ public string? mainid { get; set; }
+ ///
+ /// 检验时间
+ ///
+ public string? checktime { get; set; }
+
+ ///
+ /// 批次
+ ///
+ public string? batch { get; set; }
+
+ ///
+ /// 数据
+ ///
+ public float[] data { get; set; }
+
+ ///
+ /// 检查数量
+ ///
+ public int? checknum { get; set; }
+
+ ///
+ /// 不良品数量
+ ///
+ public int? defectivenum { get; set; }
+ }
+ public class XRchart
+ {
+ public List xcharts { get; set; }
+ public List rcharts { get; set; }
+ }
+ public class XRxchart
+ {
+ public float? x { get; set; }
+ public float? jc { get; set; }
+ public float? usl { get; set; }
+ public float? cl { get; set; }
+ public float? lsl { get; set; }
+ public float? uclx { get; set; }
+ public float? clx { get; set; }
+ public float? lclx { get; set; }
+ }
+ public class XRrchart
+ {
+ public float? r { get; set; }
+ public float? uclr { get; set; }
+ public float? clr { get; set; }
+ public float? lclr { get; set; }
+ }
+ public class XSchart
+ {
+ public List xcharts { get; set; }
+ public List scharts { get; set; }
+ }
+ public class XSxchart
+ {
+ public float? x { get; set; }
+ public float? bzc { get; set; }
+ public float? usl { get; set; }
+ public float? cl { get; set; }
+ public float? lsl { get; set; }
+ public float? uclx { get; set; }
+ public float? clx { get; set; }
+ public float? lclx { get; set; }
+ }
+ public class XSschart
+ {
+ public float? s { get; set; }
+ public float? ucls { get; set; }
+ public float? cls { get; set; }
+ public float? lcls { get; set; }
+ }
+
+ public class XMRchart
+ {
+ public List xmrxcharts { get; set; }
+ public List xmrmrcharts { get; set; }
+ }
+ public class XMRxchart
+ {
+ public float? x { get; set; }
+ public float? usl { get; set; }
+ public float? cl { get; set; }
+ public float? lsl { get; set; }
+ public float? uclx { get; set; }
+ public float? clx { get; set; }
+ public float? lclx { get; set; }
+ }
+ public class XMRmrschart
+ {
+ public float? mr { get; set; }
+ public float? uclmr { get; set; }
+ public float? clmr { get; set; }
+ public float? lclmr { get; set; }
}
}
diff --git a/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcConfig.cs b/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcConfig.cs
index 9312eb96..4cf90a08 100644
--- a/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcConfig.cs
+++ b/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcConfig.cs
@@ -28,7 +28,7 @@ namespace Tnb.QcMgr.Entities
///
/// 子组容量
///
- public string? subcapacity { get; set; }
+ public int? subcapacity { get; set; }
///
/// 控制图键
@@ -38,7 +38,7 @@ namespace Tnb.QcMgr.Entities
///
/// 控制图值
///
- public decimal? spcdata { get; set; }
+ public float? spcdata { get; set; }
}
diff --git a/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcH.cs b/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcH.cs
index f0e96a3d..2a81b63e 100644
--- a/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcH.cs
+++ b/QcMgr/Tnb.QcMgr.Entities/Entity/QcSpcH.cs
@@ -98,17 +98,17 @@ namespace Tnb.QcMgr.Entities
///
/// 规格上限
///
- public decimal? uplimit { get; set; }
+ public float? uplimit { get; set; }
///
/// 目标值
///
- public decimal? target { get; set; }
+ public float? target { get; set; }
///
/// 规格下限
///
- public decimal? lowerlimit { get; set; }
+ public float? lowerlimit { get; set; }
///
/// 子组容量
diff --git a/QcMgr/Tnb.QcMgr.Interfaces/IQcSpcService.cs b/QcMgr/Tnb.QcMgr.Interfaces/IQcSpcService.cs
index 1d6b2afb..77097e46 100644
--- a/QcMgr/Tnb.QcMgr.Interfaces/IQcSpcService.cs
+++ b/QcMgr/Tnb.QcMgr.Interfaces/IQcSpcService.cs
@@ -20,6 +20,8 @@ namespace Tnb.QcMgr.Interfaces
/// 保存spcd数据
///
///
- public Task SaveData(SpcDataInput SpcDataInput);
+ public Task SaveData(List SpcDataInput);
+
+ public Task GetSpcData(string id);
}
}
diff --git a/QcMgr/Tnb.QcMgr/QcSpcService.cs b/QcMgr/Tnb.QcMgr/QcSpcService.cs
new file mode 100644
index 00000000..297b6ca7
--- /dev/null
+++ b/QcMgr/Tnb.QcMgr/QcSpcService.cs
@@ -0,0 +1,302 @@
+using System;
+using System.ArrayExtensions;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Aspose.Cells.Drawing;
+using JNPF.Common.Core.Manager;
+using JNPF.Common.Enums;
+using JNPF.DependencyInjection;
+using JNPF.DynamicApiController;
+using JNPF.FriendlyException;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using Tnb.QcMgr.Entities;
+using Tnb.QcMgr.Entities.Entity;
+using Tnb.QcMgr.Interfaces;
+
+namespace Tnb.QcMgr
+{
+ ///
+ /// spc模块
+ ///
+ [ApiDescriptionSettings(Tag = ModuleConsts.Tag, Area = ModuleConsts.Area, Order = 800)]
+ public class QcSpcService : IQcSpcService, IDynamicApiController, ITransient
+ {
+ private readonly ISqlSugarRepository _repository;
+ private readonly IUserManager _userManager;
+ public QcSpcService(ISqlSugarRepository repository, IUserManager userManager)
+ {
+ _repository = repository;
+ _userManager = userManager;
+ }
+ ///
+ /// 获取spcd数据
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task GetSpcItems(string id)
+ {
+ var datas= await _repository.AsSugarClient().Queryable().Where(p => p.mainid == id).ToListAsync();
+ List SpcDataInputs=new List();
+ datas.ForEach(p =>
+ {
+ SpcDataInput SpcDataInput = new SpcDataInput();
+ SpcDataInput.mainid = p.mainid;
+ SpcDataInput.checktime = p.checktime;
+ SpcDataInput.batch = p.batch;
+ SpcDataInput.data = Array.ConvertAll(p.data!.Split(","),float.Parse);
+ SpcDataInput.checknum = p.checknum;
+ SpcDataInput.defectivenum = p.defectivenum;
+ SpcDataInputs.Add(SpcDataInput);
+ });
+ return SpcDataInputs;
+ }
+ ///
+ /// 保存spcd
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task SaveData(List SpcDataInput)
+ {
+ var db = _repository.AsSugarClient();
+ try
+ {
+ if (!string.IsNullOrEmpty(SpcDataInput.First().mainid))
+ await db.Deleteable(p => p.mainid == SpcDataInput.First().mainid).ExecuteCommandAsync();
+ List QcSpcDs = new List();
+
+
+ SpcDataInput.ForEach(p =>
+ {
+ QcSpcD QcSpcD=new QcSpcD();
+ QcSpcD.mainid = p.mainid;
+ QcSpcD.checktime = p.checktime;
+ QcSpcD.batch = p.batch;
+ QcSpcD.data = string.Join(",", p.data);
+ QcSpcD.checknum = p.checknum;
+ QcSpcD.defectivenum = p.defectivenum;
+ QcSpcD.create_id = _userManager.UserId;
+ QcSpcD.create_time=DateTime.Now;
+ QcSpcDs.Add(QcSpcD);
+ });
+ await db.Ado.BeginTranAsync();
+ await db.Insertable(QcSpcDs).ExecuteCommandAsync();
+ await db.Ado.CommitTranAsync();
+ }
+ catch (Exception)
+ {
+ await db.Ado.RollbackTranAsync();
+ throw Oops.Oh(ErrorCode.COM1000);
+ }
+ }
+ ///
+ /// 获取spc图表
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task GetSpcData(string id)
+ {
+ var QcSpcH = await _repository.AsSugarClient().Queryable().Where(p => p.id == id).FirstAsync();
+ var QcSpcDs = await _repository.AsSugarClient().Queryable().Where(p => p.mainid == id).ToListAsync();
+ var cinfigs = await _repository.AsSugarClient().Queryable().ToListAsync();
+ if (QcSpcH.graphtype == "X-R控制图")
+ {
+ XRchart XRchart = new XRchart();
+ XRchart.xcharts = new List();
+ XRchart.rcharts = new List();
+ foreach (var QcSpcD in QcSpcDs)
+ {
+ List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList();
+ XRxchart xchart = new XRxchart();
+ xchart.x = datas.Average();
+ xchart.jc = datas.Max() - datas.Min();
+ xchart.usl = QcSpcH.uplimit;
+ xchart.cl = QcSpcH.target;
+ xchart.lsl = QcSpcH.lowerlimit;
+ XRrchart rchart = new XRrchart();
+ rchart.r = datas.Max() - datas.Min();
+ XRchart.xcharts.Add(xchart);
+ XRchart.rcharts.Add(rchart);
+ }
+ var xAverage = XRchart.xcharts.Select(p => p.x).Average();
+ var num = XRchart.xcharts.Select(p => p.jc).Average() * cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "A2" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ XRchart.xcharts.ForEach(p =>
+ {
+ p.uclx = xAverage + num;
+ p.clx = xAverage;
+ p.lclx = xAverage - num;
+ });
+ var D4 = cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "D4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var D3 = cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "D3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var rAverage = XRchart.rcharts.Select(p => p.r).Average();
+ XRchart.rcharts.ForEach(p =>
+ {
+ p.uclr = rAverage * D4;
+ p.clr = rAverage;
+ p.lclr = rAverage * D3;
+ });
+ return XRchart;
+ }
+ if (QcSpcH.graphtype == "X-S控制图")
+ {
+ XSchart XSchart = new XSchart();
+ XSchart.xcharts = new List();
+ XSchart.scharts = new List();
+ foreach (var QcSpcD in QcSpcDs)
+ {
+ List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList();
+ XSxchart xchart = new XSxchart();
+ xchart.x = datas.Average();
+ xchart.bzc = CalculateStdDev(datas);
+ xchart.usl = QcSpcH.uplimit;
+ xchart.cl = QcSpcH.target;
+ xchart.lsl = QcSpcH.lowerlimit;
+ XSschart schart = new XSschart();
+ schart.s = CalculateStdDev(datas);
+ XSchart.xcharts.Add(xchart);
+ XSchart.scharts.Add(schart);
+ }
+ var xAverage = XSchart.xcharts.Select(p => p.x).Average();
+ var num = XSchart.xcharts.Select(p => p.bzc).Average() * cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "A3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ XSchart.xcharts.ForEach(p =>
+ {
+ p.uclx = xAverage + num;
+ p.clx = xAverage;
+ p.lclx = xAverage - num;
+ });
+ var B4 = cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "B4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var B3 = cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "B3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var sAverage = XSchart.scharts.Select(p => p.s).Average();
+ XSchart.scharts.ForEach(p =>
+ {
+ p.ucls = sAverage * B4;
+ p.cls = sAverage;
+ p.lcls = sAverage * B3;
+ });
+ return XSchart;
+ }
+ if (QcSpcH.graphtype == "X中位数-R图")
+ {
+ XRchart XRchart = new XRchart();
+ XRchart.xcharts = new List();
+ XRchart.rcharts = new List();
+ foreach (var QcSpcD in QcSpcDs)
+ {
+ List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList();
+ XRxchart xchart = new XRxchart();
+ xchart.x = CalculateMedian(datas);
+ xchart.jc = datas.Max() - datas.Min();
+ xchart.usl = QcSpcH.uplimit;
+ xchart.cl = QcSpcH.target;
+ xchart.lsl = QcSpcH.lowerlimit;
+ XRrchart rchart = new XRrchart();
+ rchart.r = datas.Max() - datas.Min();
+ XRchart.xcharts.Add(xchart);
+ XRchart.rcharts.Add(rchart);
+ }
+ var xAverage = XRchart.xcharts.Select(p => p.x).Average();
+ var num = XRchart.xcharts.Select(p => p.jc).Average() * cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "A2" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ XRchart.xcharts.ForEach(p =>
+ {
+ p.uclx = xAverage + num;
+ p.clx = xAverage;
+ p.lclx = xAverage - num;
+ });
+ var D4 = cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "D4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var D3 = cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "D3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First();
+ var rAverage = XRchart.rcharts.Select(p => p.r).Average();
+ XRchart.rcharts.ForEach(p =>
+ {
+ p.uclr = rAverage * D4;
+ p.clr = rAverage;
+ p.lclr = rAverage * D3;
+ });
+ return XRchart;
+ }
+ if (QcSpcH.graphtype == "X-MR控制图")
+ {
+ XMRchart XMRchart = new XMRchart();
+ XMRchart.xmrxcharts = new List();
+ XMRchart.xmrmrcharts = new List();
+ foreach (var QcSpcD in QcSpcDs)
+ {
+ List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList();
+ XMRxchart xchart = new XMRxchart();
+ xchart.x = datas.Average();
+ xchart.usl = QcSpcH.uplimit;
+ xchart.cl = QcSpcH.target;
+ xchart.lsl = QcSpcH.lowerlimit;
+ if (XMRchart.xmrxcharts.Count > 0)
+ {
+ XMRmrschart rchart = new XMRmrschart();
+ rchart.mr = Math.Abs((float)(xchart.x - XMRchart.xmrxcharts.Last().x)!);
+ XMRchart.xmrmrcharts.Add(rchart);
+ }
+ XMRchart.xmrxcharts.Add(xchart);
+ }
+ var xAverage = XMRchart.xmrxcharts.Select(p => p.x).Average();
+ var mrAverage = XMRchart.xmrmrcharts.Select(p => p.mr).Average();
+ XMRchart.xmrxcharts.ForEach(p =>
+ {
+ p.uclx = xAverage + (float)(2.66 * mrAverage)!;
+ p.clx = xAverage;
+ p.lclx = xAverage - (float)(2.66 * mrAverage)!;
+ });
+ XMRchart.xmrmrcharts.ForEach(p =>
+ {
+ p.uclmr = (float)(mrAverage * 3.267)!;
+ p.clmr = mrAverage;
+ p.lclmr = 0;
+ });
+ return XMRchart;
+ }
+ return null;
+ }
+ //标准差计算
+ private static float CalculateStdDev(IEnumerable values)
+ {
+ double ret = 0;
+ if (values.Count() > 0)
+ {
+ // 计算平均数
+ double avg = values.Average();
+ // 计算各数值与平均数的差值的平方,然后求和
+ double sum = values.Sum(d => Math.Pow(d - avg, 2));
+ // 除以数量,然后开方
+ ret = Math.Sqrt(sum / values.Count());
+ }
+ return (float)ret;
+ }
+ //中位数计算
+ private static float CalculateMedian(IEnumerable values)
+ {
+ float ret = 0;
+ var floats = values.OrderBy(d => d).ToArray();
+ if (floats.Count() % 2 == 0)
+ {
+ ret = (floats[floats.Count() / 2 - 1] + floats[(floats.Count() + 2) / 2 - 1]) / 2;
+ }
+ else
+ {
+ ret = floats[(floats.Count() + 1) / 2 - 1];
+ }
+ return ret;
+ }
+ //移动极差平均值计算
+ private static float CalculateMovRange(IEnumerable values)
+ {
+ List floats = new List();
+ var arr=values.ToArray();
+ for (int i = 0; i < arr.Length-1; i++)
+ {
+ floats.Add(Math.Abs((arr[i + 1] - arr[i])));
+ }
+ return floats.Average();
+ }
+ }
+}