You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

660 lines
21 KiB
C++

#include "StdAfx.h"
#include "WorkRecord.h"
#include "Propertie.h"
#include "PropertieMgr.h"
#include "AuthorityMgr.h"
#include "WorkTime.h"
#include "FileMgr.h"
#include "LogMgr.h"
#include "GlobalFunction.h"
#include "WorkFileMgr.h"
#include "CStringFuc.h"
#include "ProgramLaserTuiHuo.h"
#include "AllThreadMgr.h"
#include "WaferRecipeDataMgr.h"
#include "RecipeMgr.h"
#include "Layer.h"
#include "Laser.h"
#include "MsgBox.h"
#include "MyDlgView.h"
#include "TimingProgressMgr.h"
#include "ObjFillMgr.h"
#define RECORD_FILE_PATH _T("\\WorkRecord")
#define RECOR_JOB_ID "Job ID"
#define RECOR_LOT_ID "Lot ID"
#define RECOR_RECIPE "Recipe"
#define RECOR_LAYER_IDX "编号"
#define RECOR_START_TIME "开始时间"
#define RECOR_SPAN_TIME "加工时间"
#define RECOR_SPAN_TIME_S "加工时间(秒)"
#define RECOR_SPAN_USER_NAME "用户名"
#define RECOR_SPAN_USER_TYPE "用户类型"
#define RECOR_SPAN_START_SCAN_IDX "开始索引值"
#define RECOR_SPAN_END_SCAN_IDX "结束索引值"
#define RECOR_SPAN_TOTAL_SCAN_IDX "扫描线总数"
#define RECOR_FOCUS_Z_COORD "激光焦点位置" //退火时Z 轴的坐标值(每片wafer 可能会有点不一样)
#define RECOR_DISMETER_OFFSET "测距偏移值"//记录了当前焦点的情况
#define RECOR_LASER_SPOT_W "光斑宽度"
#define RECOR_LASER_SPOT_H "光斑高度"
#define RECOR_SET_LASER1_CURR "设定激光1 电流"
#define RECOR_SET_LASER2_CURR "设定激光2 电流"
//计时线程(用来通知观察者时间发生变化)
UINT RecordTimeThread(LPVOID pParam)
{
CWorkRecordMgr *p = (CWorkRecordMgr *)pParam;
p->UpdateCurRecordTime();
return 0;
}
CWorkRecordMgr *gWorkRecordMgr = new CWorkRecordMgr;
CWorkRecordMgr::CWorkRecordMgr(void)
{
m_CurProcessingTime = "00:00:00";
m_CurTotalWorkTime = "00:00:00";//当前总的加工时间
m_bSelWorkInfoRecord = false;//是否有选中的记录
}
CWorkRecordMgr::~CWorkRecordMgr(void)
{
}
void CWorkRecordMgr::OnAppInitialize()
{
//启动记录加工时间的线程
CWinThread* pThread;
pThread = AfxBeginThread(RecordTimeThread,this);
gAllThreadMgr.BindingThreadAdr(_EThreadType_RecordTimeThread,pThread);
//检查记录目录是否需要创建
#if 0
CString RecordPath;
CFileMgr FileMgr;
FileMgr.GetFullFilePath(RecordPath,RECORD_FILE_PATH);
if(!FileMgr.IsFileExist(RecordPath))
{
FileMgr.CreatDir(RecordPath);
}
#endif
}
//刷新当前时间进度
void CWorkRecordMgr::UpdateCurRecordTime()
{
while(1)
{
if(gAllThreadMgr.IsbStopAllThread())
break;
gAllThreadMgr.SetThreadInfoState(_EThreadType_RecordTimeThread,true);
CString SpanStr = m_WorkTime.GetTimeSpanStr();
if(SpanStr !="")
{
m_CurProcessingTime = SpanStr;//当前加工时间
}
Sleep(500);
}
gAllThreadMgr.SetThreadInfoState(_EThreadType_RecordTimeThread,false);
}
#if 1
//开始记录
void CWorkRecordMgr::StartRecord()
{
gLogMgr->WriteDebugLog("Func---->RecordMgr Start Record");
//记录加工开始时间
m_WorkStartTime = m_WorkTime.GetCurTime(":");
m_WorkTime.StartRecordTime();
//记录开始的索引值
CObjContainer &ObjContainer = gLayer.GetObjContainer();
if(_ScanStateType_AllScanned == GetCurScanStateType())
{
//重置扫描状态
ResetScanState();
gLayer.ResetAllObjScaned();
}
//记录当前扫描线的总数
m_CurScanState.m_TotalScanLineCnt = ObjContainer.GetScanLineCnt();
//记录扫描开始的idx
m_CurScanState.m_StartScanLineIdx = m_CurScanState.m_EndScanLineIdx;
m_CurScanState.m_ScanedLineCnt = 0;
GetCurScanStateType();
}
//结束记录
void CWorkRecordMgr::EndRecord()
{
m_CurScanState.m_EndScanLineIdx = m_CurScanState.m_StartScanLineIdx + m_CurScanState.m_ScanedLineCnt;
GetCurScanStateType();
//设置obj 的扫描状态
CObjContainer &ObjContainer = gLayer.GetObjContainer();
ObjContainer.SetObjScanState(m_CurScanState.m_EndScanLineIdx);
//至少要扫描一条线段才记录
if(m_CurScanState.m_ScanedLineCnt>1)
{
//保存当前的加工记录
SaveCurWorkRecord();
}
}
//停止记录时间
void CWorkRecordMgr::EndRecordTime()
{
m_WorkTime.StopRecordTime();
double SpanSecond = m_WorkTime.GetTimeSpanSecond();//经过秒数,用来计算OEE
m_CurRecordTimeSecond = Db2CString(SpanSecond);
}
#endif
#if 1
//获取当前的扫描状态
EScanStateType CWorkRecordMgr::GetCurScanStateType()
{
CString str;
EScanStateType ScanState;
int EndScanLineIdx = m_CurScanState.m_EndScanLineIdx;
int TotalScanLineCnt = m_CurScanState.m_TotalScanLineCnt;
str.Format("Par---->StartIdx[%ld]Scaned[%ld]EndIdx[%ld]Total[%ld]",m_CurScanState.m_StartScanLineIdx,m_CurScanState.m_ScanedLineCnt,EndScanLineIdx,TotalScanLineCnt);
gLogMgr->WriteDebugLog(str);
if(EndScanLineIdx==0)
{
ScanState = _ScanStateType_NotScanned;
str = ("CurScanState: _NotScanned");
}
else if(EndScanLineIdx>0 && (EndScanLineIdx < (TotalScanLineCnt)))
{
ScanState = _ScanStateType_PartiallyScanned;
str = ("CurScanState: _PartiallyScanned");
}
else if(EndScanLineIdx >= (TotalScanLineCnt))
{
ScanState = _ScanStateType_AllScanned;
str = ("CurScanState: _AllScanned");
}
else
{
ScanState = _ScanStateType_Null;
str = ("CurScanState: _Type_Null");
}
gLogMgr->WriteDebugLog(str);
return ScanState;
}
//重置扫描状态
void CWorkRecordMgr::ResetScanState()
{
gLogMgr->WriteDebugLog("Func---->ResetScanState");
m_CurScanState.m_EndScanLineIdx = 0;
m_CurScanState.m_ScanedLineCnt = 0;
}
#endif
#if 1
//获取名字为FileName 的记录路径
CString CWorkRecordMgr::GetRecordFilePath(CString FileName)
{
CString FullFilePath;
CString WorkRecordFilePath = gProgramLaserTuiHuo->GetWorkRecordFilePath();
if(WorkRecordFilePath=="")
{
CString FilePath = RECORD_FILE_PATH;
FilePath += "\\" + FileName + ".rcd";
CFileMgr FileMgr;
FileMgr.GetFullFilePath(FullFilePath,FilePath);
}
else
{
FullFilePath = WorkRecordFilePath+"\\" + FileName + ".rcd";
}
return FullFilePath;
}
//获取当前记录文件的名字(0点到24点算一天)
CString CWorkRecordMgr::GetCurRecordFileName()
{
return m_WorkTime.GetCurDate("_");
}
#endif
#if 1
//保存当前的加工记录
void CWorkRecordMgr::SaveCurWorkRecord()
{
gLogMgr->WriteDebugLog("Func---->SaveCurWorkRecord");
CWorkRecord WorkRecord;
//创建当前的加工记录
CreatCurWorkRecord(WorkRecord);
//加工记录写入到文件
WriteWorkRecordToFile(WorkRecord);
//累加CyclicWafer 数量
gProgramLaserTuiHuo->CyclicWaferInc();
}
//创建当前的加工记录
void CWorkRecordMgr::CreatCurWorkRecord(CWorkRecord &WorkRecord)
{
//创建基础信息
CreatBaseInfoRecord(WorkRecord);
//创建扫描数据信息
CreatScanDataRecord(WorkRecord);
//创建当前Recipe 信息
CreatRecipeRecord(WorkRecord);
}
//创建基础信息Record
void CWorkRecordMgr::CreatBaseInfoRecord(CWorkRecord &WorkRecord)
{
}
//创建扫描数据信息Record (显示在详细列表的内容)
void CWorkRecordMgr::CreatScanDataRecord(CWorkRecord &WorkRecord)
{
}
//创建当前Recipe 信息Record
void CWorkRecordMgr::CreatRecipeRecord(CWorkRecord &WorkRecord)
{
CRecipe Recipe = gRecipeMgr->GetCurWorkRecipe();
vector<CRecipeParameter> &RecipeParVec = Recipe.GetRecipeParVec();
int size = RecipeParVec.size();
for(int i=0;i<size;i++)
{
CRecipeParameter &RecipePar = RecipeParVec[i];
}
}
void CWorkRecordMgr::SetRecipeRecordReport(CString ParName,CString ParVal)
{
}
#endif
#if 1
//加工记录写入到文件
void CWorkRecordMgr::WriteWorkRecordToFile(CWorkRecord &WorkRecord)
{
//获取当前Record 文件路径
CString RecordFileName = GetCurRecordFileName();
CString RecordFilePath = GetRecordFilePath(RecordFileName);
CFileMgr FileMgr;
//从现有文件中读取记录的总数
int RecordCnt = 0;
bool bFileExist = FileMgr.IsFileExist(RecordFilePath);//记录是否已经存在
if(bFileExist)
{
CFile file;
if(file.Open(RecordFilePath,CFile::modeRead))
{
CArchive ar(&file,CArchive::load);
(ar)>>RecordCnt;
}
}
RecordCnt++;//增加记录的数量
//以追加的方式写入文件
{
CFile file(RecordFilePath,CFile::modeWrite|CFile::modeNoTruncate|CFile::modeCreate);
file.SeekToEnd();
CArchive ar(&file,CArchive::store);
if(!bFileExist)//第一次写入
ar<<RecordCnt;//记录的数量
vector<CRecordPar>&RecordParVec = WorkRecord.m_RecordParVec;
int ParCnt = RecordParVec.size();
ar<<ParCnt;//参数的数量
for(int k=0;k<ParCnt;k++)
{
CRecordPar &RecordPar = RecordParVec[k];
ar<<RecordPar.m_ParName;//参数名
ar<<RecordPar.m_ParVal;//参数值
}
}
if(bFileExist)//修改记录的数量
{
CFile file(RecordFilePath,CFile::modeWrite|CFile::modeNoTruncate|CFile::modeCreate);
file.Seek(0,CFile::begin);//定位到文件头
CArchive ar(&file,CArchive::store);
ar<<RecordCnt;//记录的数量
}
}
//读取路径为RecordFilePath 的记录文件
void CWorkRecordMgr::ReadWorkRecord(CString RecordFilePath)
{
CFileMgr FileMgr;
if(!FileMgr.IsFileExist(RecordFilePath))
return;
CWorkRecord WorkRecord;
//创建在列表中显示的WorkRecord
CreatListShowWorkRecord(WorkRecord);
//记录的总数
int RecordCnt = 0;
CFile file;
if(file.Open(RecordFilePath,CFile::modeRead))
{
CArchive ar(&file,CArchive::load);
(ar)>>RecordCnt;
for(int k=0;k<RecordCnt;k++)
{
CWorkRecord Record;
int ParCnt;
ar>>ParCnt;//参数的数量
for(int i=0;i<ParCnt;i++)
{
CRecordPar RecordPar;
ar>>RecordPar.m_ParName;//参数名
ar>>RecordPar.m_ParVal;//参数值
Record.AddRecordPar(RecordPar);
}
//同步ReadWorkRecord 到WorkRecord (避免存储的参数和现在不一致)
SynchWorkRecord(WorkRecord,Record);
m_ShowRecordVec.push_back(WorkRecord);
m_WorkRecordVec.push_back(Record);
}
}
}
//同步ReadWorkRecord 到WorkRecord
void CWorkRecordMgr::SynchWorkRecord(CWorkRecord &Record,CWorkRecord &ReadRecord)
{
vector<CRecordPar>&RecordParVec = Record.m_RecordParVec;
vector<CRecordPar>&ReadRecordParVec = ReadRecord.m_RecordParVec;
int ParCnt = RecordParVec.size();
for(int k=0;k<ParCnt;k++)
{
bool bFindPar = false;//是否找到
int ReadParCnt = ReadRecordParVec.size();
for(int i=0;i<ReadParCnt;i++)
{
//通过参数名进行匹配
if(RecordParVec[k].m_ParName == ReadRecordParVec[i].m_ParName)
{
RecordParVec[k].m_ParVal = ReadRecordParVec[i].m_ParVal;
bFindPar = true;
break;
}
}
//没找到说明是新加的参数
if(!bFindPar)
{
RecordParVec[k].m_ParVal = "";
}
}
}
void CWorkRecordMgr::GetAllRecordNameVec(vector<CString> &DateVec,CString StartDate,CString EndDate)
{
vector<CString> AllDateVec;
CString FullFilePath;
CFileMgr FileMgr;
CString WorkRecordFilePath = gProgramLaserTuiHuo->GetWorkRecordFilePath();
if(WorkRecordFilePath=="")
{
CString FilePath = RECORD_FILE_PATH;
FilePath += "\\";
FileMgr.GetFullFilePath(FullFilePath,FilePath);
}
else
{
FullFilePath = WorkRecordFilePath+"\\";
}
FileMgr.GetChildFileOrDirName(false,FullFilePath,AllDateVec,".rcd");
int size = AllDateVec.size();
for(int k=0;k<size;k++)
{
CString DateStr = FileMgr.GetFileNameFromPath(AllDateVec[k],true);
if(DateStr>=StartDate && DateStr<=EndDate)
DateVec.push_back(DateStr);
}
}
#endif
#if 1
//初始化工作记录list
void CWorkRecordMgr::InitWorkRecordList(CListCtrl &List)
{
//设置风格
List.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
CWorkRecord WorkRecord;
//创建在列表中显示的WorkRecord
CreatListShowWorkRecord(WorkRecord);
int idx = 0;
List.InsertColumn(idx++,"序号",LVCFMT_CENTER,50,-1);
vector<CRecordPar>&RecordParVec = WorkRecord.m_RecordParVec;
int ParCnt = RecordParVec.size();
for(int k=0;k<ParCnt;k++)
{
//设置列
CRecordPar &RecordPar = RecordParVec[k];
List.InsertColumn(idx++,RecordPar.m_ParName,LVCFMT_CENTER,RecordPar.m_ListItemWidht,-1);
}
}
//将记录插入list
void CWorkRecordMgr::InsertRecordList(CListCtrl &List,CString StartDate,CString EndDate)
{
CString log;
log += "StartDate : ";
log += StartDate;
log += " , EndDate : ";
log += EndDate;
gLogMgr->WriteDebugLog(log);
vector<CString> DateVec;
GetAllRecordNameVec(DateVec,StartDate,EndDate);
int size = DateVec.size();
int MaxWorkRecodCnt = gLogMgr->GetMaxWorkRecodCnt();
if(size>MaxWorkRecodCnt)
{
CString s;
s.Format("查询记录数量%ld 超过限制%ld",size,MaxWorkRecodCnt);
CMsgBox MsgBox;
MsgBox.Show(s);
return;
}
List.DeleteAllItems();
m_ShowRecordVec.clear();
m_WorkRecordVec.clear();
for(int k=0;k<size;k++)
{
//从Date 的record 文件读取记录
CString RecordFilePath = GetRecordFilePath(DateVec[k]);
ReadWorkRecord(RecordFilePath);
}
//插入到列表
InsertRecordListExt(List,m_ShowRecordVec);
}
void CWorkRecordMgr::InsertRecordListExt(CListCtrl &List,vector<CWorkRecord> &WorkRecordVec)
{
int size = WorkRecordVec.size();
for(int i=0;i<size;i++)
{
int idx = 0;
List.InsertItem(i," ");//插入一行
List.SetItemText(i,idx++,Int2CString(i+1));//序号
vector<CRecordPar> &RecordParVec = WorkRecordVec[i].m_RecordParVec;
int ParCnt = RecordParVec.size();
for(int k=0;k<ParCnt;k++)
{
List.SetItemText(i,idx++,RecordParVec[k].m_ParVal);
}
}
}
//创建在列表中显示的WorkRecord
void CWorkRecordMgr::CreatListShowWorkRecord(CWorkRecord &WorkRecord)
{
//创建基础信息
CreatBaseInfoRecord(WorkRecord);
//创建当前Recipe 信息
CreatRecipeRecord(WorkRecord);
}
#endif
#if 1
//初始化详细工作记录list
void CWorkRecordMgr::InitWorkRecordInfoList(CListCtrl &List)
{
//设置风格
List.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
int idx = 0;
List.InsertColumn(idx,"Idx",LVCFMT_LEFT,30,-1);
idx++;
List.InsertColumn(idx,"项目",LVCFMT_LEFT,140,-1);
idx++;
List.InsertColumn(idx,"",LVCFMT_LEFT,200,-1);
idx++;
}
void CWorkRecordMgr::InsertRecordInfoList(CListCtrl &List,int Idx)
{
List.DeleteAllItems();
int RecordCnt = m_WorkRecordVec.size();
if(Idx <0 || Idx >= RecordCnt)
return;
SetbSelWorkInfoRecord(true);
CWorkRecord &WorkRecord = m_WorkInfoRecord;
//创建在列表中显示的WorkRecord
CreatListWorkInfoRecord(WorkRecord);//只是创建一个空的WorkRecord
CWorkRecord &SelRecord = m_WorkRecordVec[Idx];
//将记录中SelRecord 参数值同步到WorkRecord 中
//因为WorkRecord 可能会有新增参数
SynchWorkRecord(WorkRecord,SelRecord);
vector<CRecordPar> &RecordParVec = WorkRecord.m_RecordParVec;
int size = RecordParVec.size();
for(int i=0;i<size;i++)
{
CRecordPar &RecordPar = RecordParVec[i];
if(RecordPar.m_ParName != "")
{
int idx = 0;
List.InsertItem(i," ");//插入一行
List.SetItemText(i,idx++,Int2CString(i+1));//序号
List.SetItemText(i,idx++,RecordPar.m_ParName);//参数名
List.SetItemText(i,idx++,RecordPar.m_ParVal);//参数值
}
}
}
//创建在列表中显示的WorkRecord
void CWorkRecordMgr::CreatListWorkInfoRecord(CWorkRecord &WorkRecord)
{
WorkRecord.Reset();
//创建基础信息
CreatBaseInfoRecord(WorkRecord);
//创建当前Recipe 信息
CreatRecipeRecord(WorkRecord);
//创建扫描数据信息
CreatScanDataRecord(WorkRecord);
}
//恢复加工记录中的recipe
void CWorkRecordMgr::RecoverRecipeByRecord()
{
gLogMgr->WriteDebugLog("Func---->OnBnClickedRecoverFormRcd");
CMsgBox MsgBox;
if(gProgramLaserTuiHuo->IsbAutoWorking())
{
gLogMgr->WriteDebugLog("加工过程中不能设置!");
return;
}
if(!gAuthorityMgr->CheckAuthority(_Authority_Engineer,true))
return;
if(!m_bSelWorkInfoRecord)
{
MsgBox.Show("请先选择需要恢复的记录!");
return;
}
if(!MsgBox.ConfirmOkCancel("从选中记录恢复recipe ?"))
return;
int EndScanIdx = 0;//扫描结束时的索引
int TotalScanIdx = 0;//扫描线总数
CRecipe RecordRecipe;
//从record 中生成recipe
vector<CRecordPar> &RecordParVec = m_WorkInfoRecord.m_RecordParVec;
int size = RecordParVec.size();
for(int k=0;k<size;k++)
{
CRecordPar &RecordPar = RecordParVec[k];
if(RecordPar.m_RecordParType==_RecordParType_Recipe)
{
vector<CRecipeParameter>&RecipeParVec = RecordRecipe.GetRecipeParVec();
int size1 = RecipeParVec.size();
for(int i=0;i<size1;i++)
{
CRecipeParameter &RecipePar = RecipeParVec[i];
if(RecipePar.m_ParShowName == RecordPar.m_ParName)
{
RecipePar.SetValByStr(RecordPar.m_ParVal);
break;
}
}
}
if(RecordPar.m_ParName == RECOR_SPAN_END_SCAN_IDX)
{
EndScanIdx = CStringToInt(RecordPar.m_ParVal);
}
if(RecordPar.m_ParName == RECOR_SPAN_TOTAL_SCAN_IDX)
{
TotalScanIdx = CStringToInt(RecordPar.m_ParVal);
}
if(RecordPar.m_ParName == RECOR_RECIPE)
{
RecordRecipe.m_RecipeName = RecordPar.m_ParVal;
}
}
int StartFillIdx = 0;
if(EndScanIdx<(TotalScanIdx-1))
{
if(MsgBox.ConfirmOkCancel("创建当前记录未扫描部分?"))
{
StartFillIdx = EndScanIdx+1-gProgramLaserTuiHuo->GetRecoverScanIdxAdjust();
}
}
gObjFillMgr.SetStartFillIdx(StartFillIdx);
CString log;
log.Format("EndScanIdx = %d,TotalScanIdx = %d,StartFillIdx = %d",EndScanIdx,TotalScanIdx,StartFillIdx);
gLogMgr->WriteDebugLog(log);
//重置扫描状态
gWorkRecordMgr->ResetScanState();
//设置当前工作用的recipe
gRecipeMgr->SetCurWorkRecipe(RecordRecipe);
gObjFillMgr.SetStartFillIdx(0);
}
//选中的加工记录导出到txt 文件
void CWorkRecordMgr::SelWrokRecordToFile()
{
gLogMgr->WriteDebugLog("Func---->SelWrokRecordToFile");
CMsgBox MsgBox;
if(!gAuthorityMgr->CheckAuthority(_Authority_Engineer,true))
return;
int RcdCnt = m_WorkRecordVec.size();
if(RcdCnt<=0)
{
CMsgBox MsgBox;
MsgBox.Show("没有要导出的记录!");
return;
}
TCHAR szFilters[]=("TXT 文件(*.txt)|*.txt");
CString FileName("WrokRecord_");
FileName += gWorkTime.GetDateTime("_","_");
CFileDialog dlg(FALSE,("txt"),FileName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilters);
CString Path = "E:\\";//默认路径
dlg.m_ofn.lpstrInitialDir = Path;
if(dlg.DoModal()==IDOK)
{
ofstream FileStream;
FileStream.open(dlg.GetPathName());
for(int k=0;k<RcdCnt;k++)
{
CWorkRecord &WorkRecord = m_WorkRecordVec[k];
vector<CRecordPar> &RecordParVec = WorkRecord.m_RecordParVec;
int size = RecordParVec.size();
for(int i=0;i<size;i++)
{
CRecordPar &RecordPar = RecordParVec[i];
if(RecordPar.m_ParName!="")
{
FileStream<<"["<<RecordPar.m_ParName<<"]"<<RecordPar.m_ParVal<<"\n";
}
}
FileStream<<"-----------------------------------------------------\n";
}
}
}
#endif