unit ProjectCommands; interface uses ProjectData, XMLDoc, XMLIntf, ProjectManagerDm, sdIDTree, sdDB, Connections; type {1. 生成临时文件夹 2. 打开项目 3. 修改项目(上报、批复相应修改) 4. 保存修改后项目的属性至xml文件 5. 保存项目至临时文件夹中 6. 压缩临时文件夹,得到上报、批复文件 7. 复制粘贴结果文件得用户选择 8. 删除临时文件夹} TReportBase = class private // 临时文件夹(生成的项目文件、xml属性文件) FTempFolder: string; FProjectName: string; FFileName: string; FProjectID: Integer; FProjectData: TProjectData; FFileType: string; // xml项目信息文件 FXmlInfoFile: string; // 结果文件 FResultFile: string; // 接收文件时是否需要升级文件 FNeedUpdate: Boolean; procedure SaveProjectInfo(AXmlNode: IXMLNode); procedure SaveTenderProperty(AXmlNode: IXMLNode); procedure SaveInfoToXmlDocument(AXmlNode: IXMLNode); procedure ExportXmlInfo; function GetNewOutputFileName: string; function CheckFile(const AFileName: string): Boolean; protected procedure OpenProject; virtual; procedure SaveProject; virtual; public constructor Create(const AProjectName, AFileName: string; AProjectID: Integer); destructor Destroy; override; function Execute: Boolean; virtual; function ExportTo(AFileName: string): Boolean; virtual; end; TSubmitProject = class(TReportBase) protected procedure OpenProject; override; procedure SaveProject; override; public function Execute: Boolean; override; function ExportTo(AFileName: string): Boolean; override; end; TReplyProject = class(TReportBase) protected procedure OpenProject; override; procedure SaveProject; override; public function Execute: Boolean; override; function ExportTo(AFileName: string): Boolean; override; end; {1. 生成临时文件夹 2. 解压选中文件至临时文件夹 3. 读取xml信息文件中的数据 4. 检查同名项目,存在则备份原项目,不存在则创建新节点 5. 根据xml文件更新数据项目信息,标段属性 6. 从临时文件夹中复制粘贴项目文件至新节点的数据文件 7. 打开该数据文件,根据情况修改 8. 保存该数据文件 9. 删除临时文件夹} TReceiveProject = class private FTempFolder: string; FFileType: string; FXmlDocument: IXMLDocument; // 导入后的节点 FCurNode: TsdIDTreeNode; FProjectName: string; FFileName: string; FSelect: TsdIDTreeNode; FProjectData: TProjectData; // 初次在线审批人,自上次Exe上报/审批 FStartAudit: Integer; // 末次在线审批人,自上次Exe上报/审批 FEndAudit: Integer; // 文件中的审核状态 FOrgAuditStatus: Integer; // 应升级至的审核状态 FNewAuditStatus: Integer; FStageCount: Integer; FReply: Boolean; FLostStageCount: Integer; // 控制是否需要升级更新文件 FNeedUpdate: Boolean; FLock: Boolean; FMessageID: Integer; FIsReback: Boolean; FWebBidName: string; function CheckOpen: Boolean; function GetNewTender: TsdIDTreeNode; procedure GetCurNode; procedure LoadProjectInfo(AXmlNode: IXMLNode); procedure LoadTenderProperty(AXmlNode: IXMLNode); procedure LoadInfoFromXmlDocument; function CheckUpdateStatusValid: Boolean; procedure ReadXmlInfo; function UpdateData(const AFileName: string): Boolean; procedure SetWebBidName(const Value: string); public constructor Create(ASelect: TsdIDTreeNode); destructor Destroy; override; function Receive(const AFileName: string): TsdIDTreeNode; // 在线审批使用 // 原报、1审(Online)、2审(Online)、3审(Online)、4审、5审(Online)、6审、7审 // 则4审在Exe端打开项目时,AStartAudit=1,AEndAudit=3 // 6审在Exe端打开项目时,AStartAudit=AEndAudit=5 // 7审在Exe端打开项目时,AStartAudit=AEndAudit=0 function ReceiveForLost(const AFileName: string; AStartAudit, AEndAudit: Integer; AReply: Boolean = False): TsdIDTreeNode; // 供网络版使用 // 原报已提交,1审已审核并提交后,此时除了2审人以外的参与人接收数据时不可生成二审数据 property Lock: Boolean read FLock write FLock; // 被打回的数据 property IsReback: Boolean read FIsReback write FIsReback; // 信息: 0[接收成功] // 1[接收失败,应接收节点打开状态] // 2[接收失败,下载文件跟网页状态不一致] // 3[接收失败,升级文件失败] property MessageID: Integer read FMessageID; // ProjectName 是标段名。之前是读自文件包中的XML文件属性,现在要从线上取。 property WebBidName: string read FWebBidName write SetWebBidName; end; {1. 生成临时文件夹 2. 保存标段的属性至xml文件 3. 复制粘贴标段文件至临时文件夹 4. 压缩临时文件夹,得到导出的标段文件(结果文件) 5. 复制粘贴结果文件得用户选择 6. 删除临时文件夹} TTenderExport = class private // 临时文件夹(生成的项目文件、xml属性文件) FTempFolder: string; FProjectName: string; FFileName: string; FProjectID: Integer; FFileType: string; // xml项目信息文件 FXmlInfoFile: string; // 结果文件 FResultFile: string; FAttachmentPath: string; procedure SaveProjectInfo(AXmlNode: IXMLNode); procedure SaveTenderProperty(AXmlNode: IXMLNode); procedure SaveInfoToXmlDocument(AXmlNode: IXMLNode); procedure ExportXmlInfo; public constructor Create(ARec: TsdDataRecord; const AFileName: string); destructor Destroy; override; // 参数AExportAttachment:是否导出附件 procedure Execute(AExportAttachment: Boolean = False); end; TTenderImport = class private FTempFolder: string; FSelect: TsdIDTreeNode; FNewNode: TsdIDTreeNode; FProjectName: string; FFileName: string; FTenderFileName: string; procedure GetNewNode; procedure LoadProjectInfo(AXmlNode: IXMLNode); procedure LoadTenderProperty(AXmlNode: IXMLNode); procedure LoadInfoFromXmlDocument(AXmlNode: IXMLNode); procedure LoadXmlInfo; public constructor Create(ASelect: TsdIDTreeNode; const AProjectName, AFileName: string); destructor Destroy; override; procedure Execute; procedure ImportToSelect; end; {1. 生成临时文件夹 2. 导出选中节点及其所有子节点信息 3. 递归所有子节点,分类(Type = 0)则新建同名文件夹,标段(Type = 1)则导出该标段 4. 压缩临时文件夹,得到导出的分类文件(结果文件) 5. 复制粘贴结果文件得用户选择 6. 删除临时文件夹} TProjectExport = class private // 临时文件夹(按层次结构生成所有项目文件) FTempFolder: string; // xml树结构文件 FXmlInfoFile: string; // 结果文件 FResultFile: string; FExportNode: TsdIDTreeNode; FTenderExportor: TTenderExport; FExportAttachment: Boolean; procedure SaveTreeNodeInfo(AXmlNode: IXMLNode; ANode: TsdIDTreeNode); procedure ExportXmlInfo; procedure ExportTender(ANode: TsdIDTreeNode; const AExportPath: string); procedure ExportNode(ANode: TsdIDTreeNode; const AExportPath: string); public constructor Create(ANode: TsdIDTreeNode; const AFileName: string; AExportAttachment: Boolean = False); destructor Destroy; override; procedure Execute; end; {1. 生成临时文件夹 2. 解压选中文件至临时文件夹 3. 根据用户选择新建子分类FNew 3. 打开Xml树结构信息文件 4. 根据Xml文件中结构,依次建立分类或导入标段文件 5. 删除临时文件夹} TProjectImport = class private FTempFolder: string; FProjectName: string; FFileName: string; FSelect: TsdIDTreeNode; FNew: TsdIDTreeNode; function AddNewNode(AParentID, ANextID: Integer; const ANodeName: string): TsdIDTreeNode; procedure LoadTender(AXmlNode: IXMLNode; AParent: TsdIDTreeNode; const APath: string); procedure LoadChild(AXmlNode: IXMLNode; AParent: TsdIDTreeNode; const APath: string); procedure LoadChildrenFormXml; public constructor Create(ASelect: TsdIDTreeNode; const AProjectName, AFileName: string); destructor Destroy; override; procedure Execute; end; // 文件检验 { 检验分为两部分: 1. 一致性检验:检验文件中的xml记录数据,与数据库中数据是否一致,以检验文件是否可用 2. 主动检验: 提供xml记录的部分数据,用户主动检验是否为所需文件 流程: 1. 解压文件,得到xml文件,项目文件 2. 读取xml文件,得到主要数据,与项目文件名 3. 读取项目文件,并检验基本数据是否与xml文件中描述一致 PS:用于主动检验的数据,在第2步中同步进行。要求,如果进行主动检验,必须先通过一致性检验。 } TTenderFileChecker = class private FFileName: string; FTempFolder: string; FTenderFileName: string; FTenderTempFolder: string; FValid: Boolean; FPhaseCount: Integer; FAuditStatus: Integer; FProjectName: string; procedure LoadProjectInfo(AXmlNode: IXMLNode); procedure LoadInfoFromXmlDocument(AXmlNode: IXMLNode); procedure LoadInfoFromXml; procedure LoadInfo; function DecryptFile(const AFileName: string): Boolean; function CheckFileMatchXml: Boolean; public // 检验项目数据库数据与xml文件中主要数据是否吻合 function CheckFileValid(const AFileName: string): Boolean; // xml文件中记录的信息,用于主动检验 property PhaseCount: Integer read FPhaseCount; property AuditStatus: Integer read FAuditStatus; end; TTenderZipCheckType = (zctAllPhase, zctLastPhase); // 文件检验 TTenderZipCompleteChecker = class private FFileName: string; FTempFolder: string; FProjectData: TProjectData; FCheckType: TTenderZipCheckType; function CheckMain: Boolean; function CheckAllPhase: Boolean; function CheckLastPhase: Boolean; public constructor Create; destructor Destroy; override; function CheckFileValid(const AFileName: string): Boolean; property CheckType: TTenderZipCheckType read FCheckType write FCheckType; end; TmtfFileView = class private FTempFolder: string; FSelect: TsdIDTreeNode; FNewNode: TsdIDTreeNode; FFileName: string; FTenderFileName: string; procedure LoadProjectInfo(AXmlNode: IXMLNode); procedure LoadInfoFromXmlDocument(AXmlNode: IXMLNode); procedure LoadXmlInfo; public constructor Create(const AFileName: string); destructor Destroy; override; property FileName: String read FFileName; end; implementation uses UtilMethods, ZhAPI, Globals, SysUtils, SupportUnit, NewProjectFrm, PhaseData, ConfigDoc, ConstUnit, PHPWebDm; { TSubmitProject } function TSubmitProject.Execute: Boolean; begin FFileType := '.rmf'; FNeedUpdate := True; //FProjectData.LockedDataForSubmit; Result := inherited Execute; end; function TSubmitProject.ExportTo(AFileName: string): Boolean; begin FNeedUpdate := True; //FProjectData.LockedDataForSubmit; Result := inherited ExportTo(AFileName); end; procedure TSubmitProject.OpenProject; begin FProjectData.OpenForSubmit(FFileName); end; procedure TSubmitProject.SaveProject; begin FProjectData.SaveAsForSubmit(FTempFolder + '\' + ExtractSimpleFileName(FFileName)); end; { TReportBase } constructor TReportBase.Create(const AProjectName, AFileName: string; AProjectID: Integer); begin FProjectName := AProjectName; FFileName := AFileName; FProjectID := AProjectID; FProjectData := TProjectData.Create; FFileType := '.dat'; FTempFolder := GenerateTempFolder(GetTempFilePath); FXmlInfoFile := FTempFolder + '\Info.xml'; FResultFile := GetTempFileName; FNeedUpdate := False; OpenProject; end; destructor TReportBase.Destroy; begin DeleteFileOrFolder(FTempFolder); DeleteFileOrFolder(FResultFile); FProjectData.Free; inherited; end; function TReportBase.Execute: Boolean; var sFileName: string; begin Result := False; ExportXmlInfo; SaveProject; ZipFolder(FTempFolder, FResultFile); // 检验导出文件 if CheckFile(FResultFile) then begin Result := True; sFileName := GetNewOutputFileName; if SaveFile(sFileName, FFileType) then CopyFileOrFolder(FResultFile, sFileName); end; end; function TReportBase.ExportTo(AFileName: string): Boolean; begin Result := False; ExportXmlInfo; FProjectData.SimpleSaveAs(FTempFolder + '\' + ExtractSimpleFileName(FFileName)); ZipFolder(FTempFolder, FResultFile); if CheckFile(FResultFile) then begin Result := True; CopyFileOrFolder(FResultFile, AFileName); end; end; procedure TReportBase.ExportXmlInfo; var FXmlDocument: IXMLDocument; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAttrNull,doAutoPrefix,doNamespaceDecl]; FXmlDocument.Active := True; FXmlDocument.Encoding := 'GB2312'; FXmlDocument.AddChild('ProjectMangerInfo'); SaveInfoToXmlDocument(FXmlDocument.DocumentElement); FXmlDocument.SaveToFile(FXmlInfoFile); finally FXmlDocument := nil; end; end; function TReportBase.GetNewOutputFileName: string; begin Result := SupportManager.ConfigInfo.AuditPath + FProjectName + Format('-第%d期', [FProjectData.ProjProperties.PhaseCount]); if FProjectData.ProjProperties.AuditCompany <> '' then Result := Result + '-' + FProjectData.ProjProperties.AuditCompany; Result := Result + Format('-%s-', [FProjectData.ProjProperties.AuditStatusStr]) + FormatDateTime('yyyy-mm-dd', Date) + FFileType; end; procedure TReportBase.OpenProject; begin FProjectData.SimpleOpen(FFileName); end; procedure TReportBase.SaveProject; begin FProjectData.SimpleSaveAs(FTempFolder + '\' + ExtractSimpleFileName(FFileName)); end; procedure TReportBase.SaveInfoToXmlDocument(AXmlNode: IXMLNode); begin SaveProjectInfo(AXmlNode); SaveTenderProperty(AXmlNode); end; procedure TReportBase.SaveProjectInfo(AXmlNode: IXMLNode); var vInfo: IXMLNode; InfoRec: TsdDataRecord; begin vInfo := AXmlNode.AddChild('ProjectInfo'); InfoRec := ProjectManager.sddProjectsInfo.FindKey('idxID', FProjectID); vInfo.Attributes['ProjectName'] := FProjectName; vInfo.Attributes['NeedUpdate'] := FNeedUpdate; vInfo.Attributes['DealTotalPrice'] := InfoRec.ValueByName('DealTotalPrice').AsFloat; vInfo.Attributes['PhaseTotalPrice'] := InfoRec.ValueByName('PhaseTotalPrice').AsFloat; vInfo.Attributes['EndDealTotalPrice'] := InfoRec.ValueByName('EndDealTotalPrice').AsFloat; vInfo.Attributes['EndChangeTotalPrice'] := InfoRec.ValueByName('EndChangeTotalPrice').AsFloat; vInfo.Attributes['EndTotalPrice'] := InfoRec.ValueByName('EndTotalPrice').AsFloat; vInfo.Attributes['PreTotalPrice'] := InfoRec.ValueByName('PreTotalPrice').AsFloat; vInfo.Attributes['PhasePay'] := InfoRec.ValueByName('PhasePay').AsFloat; vInfo.Attributes['EndPhasePay'] := InfoRec.ValueByName('EndPhasePay').AsFloat; vInfo.Attributes['Deal_BGLTotalPrice'] := InfoRec.ValueByName('Deal_BGLTotalPrice').AsFloat; vInfo.Attributes['PhaseCount'] := FProjectData.ProjProperties.PhaseCount; vInfo.Attributes['AuditStatus'] := FProjectData.ProjProperties.AuditStatus; vInfo.Attributes['FileName'] := ExtractSimpleFileName(FFileName); vInfo.Attributes['CommonDigit'] := InfoRec.ValueByName('CommonDigit').AsInteger; vInfo.Attributes['DealPayDigit'] := InfoRec.ValueByName('DealPayDigit').AsInteger; if G_IsCloud then begin vInfo.Attributes['WebID'] := InfoRec.ValueByName('WebID').AsInteger; vInfo.Attributes['WebOwnerID'] := InfoRec.ValueByName('WebOwnerID').AsInteger; vInfo.Attributes['WebAuthorID'] := InfoRec.ValueByName('WebAuthorID').AsInteger; end; end; procedure TReportBase.SaveTenderProperty(AXmlNode: IXMLNode); var vProp: IXMLNode; begin vProp := AXmlNode.AddChild('TenderProperty'); end; function TReportBase.CheckFile(const AFileName: string): Boolean; var vChecker: TTenderFileChecker; begin Result := False; vChecker := TTenderFileChecker.Create; try Result := vChecker.CheckFileValid(AFileName); finally vChecker.Free; end; end; { TReplyProject } function TReplyProject.Execute: Boolean; begin FFileType := '.arf'; FProjectData.LockedDataForReply; Result := inherited Execute; end; function TReplyProject.ExportTo(AFileName: string): Boolean; begin FProjectData.LockedDataForReply; Result := inherited ExportTo(AFileName); end; procedure TReplyProject.OpenProject; begin FProjectData.OpenForReply(FFileName); end; procedure TReplyProject.SaveProject; begin FProjectData.SaveForReply(FTempFolder + '\' + ExtractSimpleFileName(FFileName)); end; { TReceiveProject } function TReceiveProject.CheckUpdateStatusValid: Boolean; procedure GetCurAuditStatus; begin {if FStageCount > 0 then FLostStageCount := FStageCount - (AXmlNode.Attributes['AuditStatus'] + 1) - 1; if FNeedUpdate then begin if FReply then Result := -1 else if FStageCount > 0 then Result := FStageCount - 1 else Result := AXmlNode.Attributes['AuditStatus'] + 1 end else Result := AXmlNode.Attributes['AuditStatus'];} end; var ChildNodes: IXMLNodeList; vProjInfo, vXmlElement: IXMLNode; begin Result := True; vXmlElement := FXmlDocument.DocumentElement; ChildNodes := vXmlElement.ChildNodes; vProjInfo := ChildNodes.FindNode('ProjectInfo'); FFileName := vProjInfo.Attributes['FileName']; FNeedUpdate := vProjInfo.Attributes['NeedUpdate']; FOrgAuditStatus := vProjInfo.Attributes['AuditStatus']; if not FIsReback and FNeedUpdate then begin if FStartAudit <> 0 then begin if (FStartAudit <> FOrgAuditStatus + 1) or (FEndAudit < FStartAudit) then Result := False else FLostStageCount := FEndAudit - FStartAudit + 1 + 1; end else FLostStageCount := 1; // 锁定的情况下 if FLock then FLostStageCount := FLostStageCount - 1; if FReply then FNewAuditStatus := -1 else FNewAuditStatus := FOrgAuditStatus + FLostStageCount; end else FNewAuditStatus := FOrgAuditStatus; end; function TReceiveProject.CheckOpen: Boolean; begin Result := OpenProjectManager.ProjectIndex(FCurNode.ID) <> -1; if Result then FMessageID := 1; end; constructor TReceiveProject.Create(ASelect: TsdIDTreeNode); begin FSelect := ASelect; FTempFolder := GenerateTempFolder(GetTempFilePath); FReply := False; FLock := False; FMessageID := 0; FIsReback := False; FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; end; destructor TReceiveProject.Destroy; begin FXmlDocument := nil; DeleteFileOrFolder(FTempFolder); inherited; end; procedure TReceiveProject.GetCurNode; var I: Integer; begin if FSelect.Rec.ValueByName('Type').AsInteger = 0 then FCurNode := FSelect.FirstChild else FCurNode := FSelect.Parent.FirstChild; while Assigned(FCurNode) and (FCurNode.Rec.ValueByName('Name').AsString <> FProjectName) do FCurNode := FCurNode.NextSibling; if not Assigned(FCurNode) then FCurNode := GetNewTender else if CheckOpen then Abort; end; function TReceiveProject.GetNewTender: TsdIDTreeNode; begin if FSelect.Rec.ValueByName('Type').AsInteger = 0 then Result := ProjectManager.ProjectsTree.Add(FSelect.ID, -1) else Result := ProjectManager.ProjectsTree.Add(FSelect.ParentID, FSelect.NextSiblingID); Result.Rec.ValueByName('Name').AsString := FProjectName; Result.Rec.ValueByName('Type').AsInteger := 1; Result.Rec.ValueByName('FileName').AsString := ExtractSimpleFileName(GetNewGUIDFileName(GetMyProjectsFilePath)); end; procedure TReceiveProject.LoadInfoFromXmlDocument; var ChildNodes: IXMLNodeList; vProjInfo, vXmlElement: IXMLNode; begin vXmlElement := FXmlDocument.DocumentElement; ChildNodes := vXmlElement.ChildNodes; vProjInfo := ChildNodes.FindNode('ProjectInfo'); if (G_IsCloud and (FWebBidName <> '')) then FProjectName := FWebBidName else FProjectName := vProjInfo.Attributes['ProjectName']; GetCurNode; // 备份旧文件 // 备份须放在这里的原因是,需要打开xml文件后,才能确认是否要备份文件以及应备份哪个文件 // 但是又不能再导入xml数据以后,导入xml数据后,项目的属性会变掉 ProjectManager.RestoreTender(FCurNode.ID); LoadProjectInfo(ChildNodes.FindNode('ProjectInfo')); LoadTenderProperty(ChildNodes.FindNode('TenderProperty')); end; procedure TReceiveProject.LoadProjectInfo(AXmlNode: IXMLNode); begin FCurNode.Rec.ValueByName('DealTotalPrice').AsFloat := AXmlNode.Attributes['DealTotalPrice']; FCurNode.Rec.ValueByName('PhaseTotalPrice').AsFloat := AXmlNode.Attributes['PhaseTotalPrice']; FCurNode.Rec.ValueByName('EndDealTotalPrice').AsFloat := AXmlNode.Attributes['EndDealTotalPrice']; FCurNode.Rec.ValueByName('EndChangeTotalPrice').AsFloat := AXmlNode.Attributes['EndChangeTotalPrice']; FCurNode.Rec.ValueByName('EndTotalPrice').AsFloat := AXmlNode.Attributes['EndTotalPrice']; FCurNode.Rec.ValueByName('PreTotalPrice').AsFloat := AXmlNode.Attributes['PreTotalPrice']; FCurNode.Rec.ValueByName('PhasePay').AsFloat := AXmlNode.Attributes['PhasePay']; FCurNode.Rec.ValueByName('EndPhasePay').AsFloat := VarToFloatDef(AXmlNode.Attributes['EndPhasePay'], 0); if AXmlNode.HasAttribute('Deal_BGLTotalPrice') then FCurNode.Rec.ValueByName('Deal_BGLTotalPrice').AsFloat := AXmlNode.Attributes['Deal_BGLTotalPrice']; FCurNode.Rec.ValueByName('PhaseCount').AsInteger := AXmlNode.Attributes['PhaseCount']; FCurNode.Rec.ValueByName('AuditStatus').AsInteger := FNewAuditStatus; FCurNode.Rec.ValueByName('CreateDate').AsString := FormatDateTime('yyyy-mm-dd', Date); FCurNode.Rec.ValueByName('CommonDigit').AsInteger := StrToIntDef(AXmlNode.Attributes['CommonDigit'], 0); FCurNode.Rec.ValueByName('DealPayDigit').AsInteger := StrToIntDef(AXmlNode.Attributes['DealPayDigit'], 0); if G_IsCloud then begin FCurNode.Rec.ValueByName('WebID').AsInteger := AXmlNode.Attributes['WebID']; FCurNode.Rec.ValueByName('WebOwnerID').AsInteger := AXmlNode.Attributes['WebOwnerID']; FCurNode.Rec.ValueByName('WebAuthorID').AsInteger := AXmlNode.Attributes['WebAuthorID']; end; ProjectManager.CalculateParentInfo(FCurNode.ParentID); end; procedure TReceiveProject.LoadTenderProperty(AXmlNode: IXMLNode); begin // ToDo end; procedure TReceiveProject.ReadXmlInfo; begin FXmlDocument.LoadFromFile(FTempFolder + '\Info.xml'); FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl]; end; function TReceiveProject.Receive(const AFileName: string): TsdIDTreeNode; begin Result := nil; FFileType := ExtractFileExt(AFileName); UnZipFile(AFileName, FTempFolder); ReadXmlInfo; if CheckUpdateStatusValid then begin if UpdateData(FTempFolder + '\' + FFileName) then begin LoadInfoFromXmlDocument; CopyFileOrFolder(FTempFolder + '\' + FFileName, GetMyProjectsFilePath + FCurNode.Rec.ValueByName('FileName').AsString); Result := FCurNode; end else FMessageID := 3; end else FMessageID := 2; end; function TReceiveProject.ReceiveForLost(const AFileName: string; AStartAudit, AEndAudit: Integer; AReply: Boolean = False): TsdIDTreeNode; begin FStartAudit := AStartAudit; FEndAudit := AEndAudit; FReply := AReply; Result := Receive(AFileName); end; function TReceiveProject.UpdateData(const AFileName: string): Boolean; var I: Integer; begin if not IsReback and FNeedUpdate then begin Result := False; FProjectData := TProjectData.Create; try FProjectData.OpenForReceive(AFileName); FProjectData.LockedDataForSubmit; for I := 0 to FLostStageCount - 1 do FProjectData.UpdateDataForReceive; if FReply then FProjectData.LockedDataForReply; FProjectData.SaveForReceive(AFileName); Result := True; finally FProjectData.Free; end; end else Result := True; end; procedure TReceiveProject.SetWebBidName(const Value: string); begin FWebBidName := Value; end; { TTenderExport } constructor TTenderExport.Create(ARec: TsdDataRecord; const AFileName: string); begin FProjectName := ARec.ValueByName('Name').AsString; FFileName := GetMyProjectsFilePath + ARec.ValueByName('FileName').AsString; if not G_IsCloud then FAttachmentPath := GetMyProjectsFilePath + 'Attachment\' + ARec.ValueByName('FileName').AsString + '\'; FProjectID := ARec.ValueByName('ID').AsInteger; FTempFolder := GenerateTempFolder(GetTempFilePath); FXmlInfoFile := FTempFolder + '\Info.xml'; FResultFile := AFileName; end; destructor TTenderExport.Destroy; begin DeleteFileOrFolder(FTempFolder); inherited; end; procedure TTenderExport.Execute(AExportAttachment: Boolean); var sFileName: string; begin ExportXmlInfo; sFileName := ExtractSimpleFileName(FResultFile); CopyFileOrFolder(FFileName, FTempFolder + '\' + sFileName); // if not G_IsCloud then // 云版不导出附件,云版的运作机制是从网上下载 // if AExportAttachment then // CopyFolder(FAttachmentPath, FTempFolder + '\' + sFileName + '[附件包]'); ZipFolder(FTempFolder, FResultFile); end; procedure TTenderExport.ExportXmlInfo; var FXmlDocument: IXMLDocument; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAttrNull,doAutoPrefix,doNamespaceDecl]; FXmlDocument.Active := True; FXmlDocument.Encoding := 'GB2312'; FXmlDocument.AddChild('ProjectMangerInfo'); SaveInfoToXmlDocument(FXmlDocument.DocumentElement); FXmlDocument.SaveToFile(FXmlInfoFile); finally FXmlDocument := nil; end; end; procedure TTenderExport.SaveInfoToXmlDocument(AXmlNode: IXMLNode); begin SaveProjectInfo(AXmlNode); SaveTenderProperty(AXmlNode); end; procedure TTenderExport.SaveProjectInfo(AXmlNode: IXMLNode); var vInfo: IXMLNode; InfoRec: TsdDataRecord; begin vInfo := AXmlNode.AddChild('ProjectInfo'); InfoRec := ProjectManager.sddProjectsInfo.FindKey('idxID', FProjectID); vInfo.Attributes['ProjectName'] := FProjectName; vInfo.Attributes['DealTotalPrice'] := InfoRec.ValueByName('DealTotalPrice').AsFloat; vInfo.Attributes['PhaseTotalPrice'] := InfoRec.ValueByName('PhaseTotalPrice').AsFloat; vInfo.Attributes['EndDealTotalPrice'] := InfoRec.ValueByName('EndDealTotalPrice').AsFloat; vInfo.Attributes['EndChangeTotalPrice'] := InfoRec.ValueByName('EndChangeTotalPrice').AsFloat; vInfo.Attributes['EndTotalPrice'] := InfoRec.ValueByName('EndTotalPrice').AsFloat; vInfo.Attributes['PreTotalPrice'] := InfoRec.ValueByName('PreTotalPrice').AsFloat; vInfo.Attributes['PhasePay'] := InfoRec.ValueByName('PhasePay').AsFloat; vInfo.Attributes['EndPhasePay'] := VarToFloatDef(InfoRec.ValueByName('EndPhasePay').AsFloat, 0); vInfo.Attributes['Deal_BGLTotalPrice'] := InfoRec.ValueByName('Deal_BGLTotalPrice').AsFloat; vInfo.Attributes['PhaseCount'] := InfoRec.ValueByName('PhaseCount').AsInteger; vInfo.Attributes['AuditStatus'] := InfoRec.ValueByName('AuditStatus').AsInteger; vInfo.Attributes['FileName'] := ExtractSimpleFileName(FResultFile); vInfo.Attributes['CommonDigit'] := InfoRec.ValueByName('CommonDigit').AsInteger; vInfo.Attributes['DealPayDigit'] := InfoRec.ValueByName('DealPayDigit').AsInteger; if G_IsCloud then begin vInfo.Attributes['WebID'] := InfoRec.ValueByName('WebID').AsInteger; vInfo.Attributes['WebOwnerID'] := InfoRec.ValueByName('WebOwnerID').AsInteger; vInfo.Attributes['WebAuthorID'] := InfoRec.ValueByName('WebAuthorID').AsInteger; end; end; procedure TTenderExport.SaveTenderProperty(AXmlNode: IXMLNode); var vProp: IXMLNode; begin vProp := AXmlNode.AddChild('TenderProperty'); end; { TProjectExport } constructor TProjectExport.Create(ANode: TsdIDTreeNode; const AFileName: string; AExportAttachment: Boolean); begin FTempFolder := GenerateTempFolder(GetTempFilePath); FExportNode := ANode; FResultFile := AFileName; FExportAttachment := AExportAttachment; FXmlInfoFile := FTempFolder + '\TreeInfo.xml'; end; destructor TProjectExport.Destroy; begin DeleteFileOrFolder(FTempFolder); inherited; end; procedure TProjectExport.Execute; begin ExportXmlInfo; ExportNode(FExportNode.FirstChild, FTempFolder + '\'); ZipFolder(FTempFolder, FResultFile); end; procedure TProjectExport.ExportNode(ANode: TsdIDTreeNode; const AExportPath: string); var ACurPath: string; begin if not Assigned(ANode) then Exit; if ANode.HasChildren or (ANode.Rec.ValueByName('Type').AsInteger = 0) then begin ACurPath := AExportPath + ANode.Rec.ValueByName('Name').AsString + '\'; CreateDirectoryInDeep(ACurPath); ExportNode(ANode.FirstChild, ACurPath); end else ExportTender(ANode, AExportPath); ExportNode(ANode.NextSibling, AExportPath); end; procedure TProjectExport.ExportTender(ANode: TsdIDTreeNode; const AExportPath: string); begin FTenderExportor := TTenderExport.Create(ANode.Rec, AExportPath + ANode.Rec.ValueByName('Name').AsString); try FTenderExportor.Execute(FExportAttachment); finally FTenderExportor.Free; end; end; procedure TProjectExport.ExportXmlInfo; var FXmlDocument: IXMLDocument; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAttrNull,doAutoPrefix,doNamespaceDecl]; FXmlDocument.Active := True; FXmlDocument.Encoding := 'GB2312'; FXmlDocument.AddChild('ProjectTreeInfo'); SaveTreeNodeInfo(FXmlDocument.DocumentElement, FExportNode.FirstChild); FXmlDocument.SaveToFile(FXmlInfoFile); finally FXmlDocument := nil; end; end; procedure TProjectExport.SaveTreeNodeInfo(AXmlNode: IXMLNode; ANode: TsdIDTreeNode); var CurNode: IXMLNode; begin if not Assigned(ANode) then Exit; CurNode := AXmlNode.AddChild('TreeNode'); CurNode.Attributes['Name'] := ANode.Rec.ValueByName('Name').AsString; CurNode.Attributes['Type'] := ANode.Rec.ValueByName('Type').AsInteger; if ANode.HasChildren then SaveTreeNodeInfo(CurNode, ANode.FirstChild); SaveTreeNodeInfo(AXmlNode, ANode.NextSibling); end; { TProjectImport } function TProjectImport.AddNewNode(AParentID, ANextID: Integer; const ANodeName: string): TsdIDTreeNode; begin with ProjectManager.ProjectsTree do Result := Add(AParentID, ANextID); Result.Rec.ValueByName('Name').AsString := ANodeName; Result.Rec.ValueByName('Type').AsInteger := 0; end; constructor TProjectImport.Create(ASelect: TsdIDTreeNode; const AProjectName, AFileName: string); begin FSelect := ASelect; FProjectName := AProjectName; FFileName := AFileName; FTempFolder := GenerateTempFolder(GetTempFilePath); end; destructor TProjectImport.Destroy; begin DeleteFileOrFolder(FTempFolder); inherited; end; procedure TProjectImport.Execute; begin UnZipFile(FFileName, FTempFolder); // ID 188 需求变更,一直作为后兄弟节点导入 {if FSelect.Rec.ValueByName('Type').AsInteger = 1 then FNew := AddNewNode(FSelect.ParentID, FSelect.NextSiblingID, FProjectName) else FNew := AddNewNode(FSelect.ID, -1, FProjectName);} if Assigned(FSelect) then FNew := AddNewNode(FSelect.ParentID, FSelect.NextSiblingID, FProjectName) else FNew := AddNewNode(-1, -1, FProjectName); LoadChildrenFormXml; end; procedure TProjectImport.LoadChild(AXmlNode: IXMLNode; AParent: TsdIDTreeNode; const APath: string); var I, iType: Integer; XmlNode: IXMLNode; stnNewNode: TsdIDTreeNode; begin for I := 0 to AXmlNode.ChildNodes.Count - 1 do begin XmlNode := AXmlNode.ChildNodes.Get(I); iType := XmlNode.Attributes['Type']; if iType = 0 then begin stnNewNode := AddNewNode(AParent.ID, -1, XmlNode.Attributes['Name']); if XmlNode.HasChildNodes then LoadChild(XmlNode, stnNewNode, APath + XmlNode.Attributes['Name'] + '\'); end else LoadTender(XmlNode, AParent, APath); end; end; procedure TProjectImport.LoadChildrenFormXml; var FXmlDocument: IXMLDocument; XmlNode: IXMLNode; FRootList: IXMLNodeList; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.LoadFromFile(FTempFolder + '\TreeInfo.xml'); FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl]; XmlNode := FXmlDocument.DocumentElement; LoadChild(XmlNode, FNew, FTempFolder + '\'); finally FRootList := nil; FXmlDocument := nil; end; end; procedure TProjectImport.LoadTender(AXmlNode: IXMLNode; AParent: TsdIDTreeNode; const APath: string); var TenderImportor: TTenderImport; begin TenderImportor := TTenderImport.Create(AParent, AXmlNode.Attributes['Name'], APath + AXmlNode.Attributes['Name']); try TenderImportor.Execute; finally TenderImportor.Free; end; end; { TTenderImport } constructor TTenderImport.Create(ASelect: TsdIDTreeNode; const AProjectName, AFileName: string); begin FSelect := ASelect; FProjectName := AProjectName; FFileName := AFileName; FTempFolder := GenerateTempFolder(GetTempFilePath); end; destructor TTenderImport.Destroy; begin DeleteFileOrFolder(FTempFolder); inherited; end; procedure TTenderImport.Execute; var sFile, sFJ: string; begin UnZipFile(FFileName, FTempFolder); GetNewNode; LoadXmlInfo; sFile := FTempFolder + '\' + FTenderFileName; // sFJ := sFile + '[附件包]'; CopyFileOrFolder(sFile, GetMyProjectsFilePath + FNewNode.Rec.ValueByName('FileName').AsString); // if not G_IsCloud then // 云版附件从服务器获取,不导入。 // if DirectoryExists(sFJ) then // CopyFolder(sFJ, GetMyProjectsFilePath + 'Attachment\' + FNewNode.Rec.ValueByName('FileName').AsString); end; procedure TTenderImport.GetNewNode; begin if FSelect.Rec.ValueByName('Type').AsInteger = 1 then FNewNode := ProjectManager.ProjectsTree.Add(FSelect.ParentID, FSelect.NextSiblingID) else FNewNode := ProjectManager.ProjectsTree.Add(FSelect.ID, -1); FNewNode.Rec.ValueByName('Name').AsString := FProjectName; FNewNode.Rec.ValueByName('Type').AsInteger := 1; FNewNode.Rec.ValueByName('FileName').AsString := ExtractSimpleFileName(GetNewGUIDFileName(GetMyProjectsFilePath)); end; procedure TTenderImport.ImportToSelect; begin UnZipFile(FFileName, FTempFolder); FNewNode := FSelect; LoadXmlInfo; CopyFileOrFolder(FTempFolder + '\' + FTenderFileName, GetMyProjectsFilePath + FNewNode.Rec.ValueByName('FileName').AsString); end; procedure TTenderImport.LoadInfoFromXmlDocument(AXmlNode: IXMLNode); var ChildNodes: IXMLNodeList; begin ChildNodes := AXmlNode.ChildNodes; LoadProjectInfo(ChildNodes.FindNode('ProjectInfo')); LoadTenderProperty(ChildNodes.FindNode('TenderProperty')); end; procedure TTenderImport.LoadProjectInfo(AXmlNode: IXMLNode); begin FTenderFileName := AXmlNode.Attributes['FileName']; FNewNode.Rec.ValueByName('DealTotalPrice').AsFloat := AXmlNode.Attributes['DealTotalPrice']; FNewNode.Rec.ValueByName('PhaseTotalPrice').AsFloat := AXmlNode.Attributes['PhaseTotalPrice']; FNewNode.Rec.ValueByName('EndDealTotalPrice').AsFloat := AXmlNode.Attributes['EndDealTotalPrice']; FNewNode.Rec.ValueByName('EndChangeTotalPrice').AsFloat := AXmlNode.Attributes['EndChangeTotalPrice']; FNewNode.Rec.ValueByName('EndTotalPrice').AsFloat := AXmlNode.Attributes['EndTotalPrice']; FNewNode.Rec.ValueByName('PreTotalPrice').AsFloat := AXmlNode.Attributes['PreTotalPrice']; FNewNode.Rec.ValueByName('PhasePay').AsFloat := VarToFloatDef(AXmlNode.Attributes['PhasePay'], 0); FNewNode.Rec.ValueByName('EndPhasePay').AsFloat := VarToFloatDef(AXmlNode.Attributes['EndPhasePay'], 0); if AXmlNode.HasAttribute('Deal_BGLTotalPrice') then FNewNode.Rec.ValueByName('Deal_BGLTotalPrice').AsFloat := AXmlNode.Attributes['Deal_BGLTotalPrice']; FNewNode.Rec.ValueByName('PhaseCount').AsInteger := AXmlNode.Attributes['PhaseCount']; FNewNode.Rec.ValueByName('AuditStatus').AsInteger := AXmlNode.Attributes['AuditStatus']; FNewNode.Rec.ValueByName('CreateDate').AsString := FormatDateTime('yyyy-mm-dd', Date); FNewNode.Rec.ValueByName('CommonDigit').AsInteger := StrToIntDef(AXmlNode.Attributes['CommonDigit'], 0); FNewNode.Rec.ValueByName('DealPayDigit').AsInteger := StrToIntDef(AXmlNode.Attributes['DealPayDigit'], 0); if G_IsCloud then begin FNewNode.Rec.ValueByName('WebID').AsInteger := AXmlNode.Attributes['WebID']; FNewNode.Rec.ValueByName('WebOwnerID').AsInteger := AXmlNode.Attributes['WebOwnerID']; FNewNode.Rec.ValueByName('WebAuthorID').AsInteger := AXmlNode.Attributes['WebAuthorID']; end; ProjectManager.CalculateParentInfo(FNewNode.ParentID); end; procedure TTenderImport.LoadTenderProperty(AXmlNode: IXMLNode); begin // TODO end; procedure TTenderImport.LoadXmlInfo; var FXmlDocument: IXMLDocument; XmlNode: IXMLNode; FRootList: IXMLNodeList; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.LoadFromFile(FTempFolder + '\Info.xml'); FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl]; XmlNode := FXmlDocument.DocumentElement; LoadInfoFromXmlDocument(XmlNode); finally FRootList := nil; FXmlDocument := nil; end; end; { TTenderFileChecker } function TTenderFileChecker.CheckFileMatchXml: Boolean; var FProjectData: TProjectData; begin FProjectData := TProjectData.Create; try try FProjectData.SimpleOpen(FTenderFileName); Result := FProjectData.CheckDataBaseInfo(FPhaseCount, FAuditStatus); except Result := False; end; finally FProjectData.Free; end; end; function TTenderFileChecker.CheckFileValid(const AFileName: string): Boolean; begin FTempFolder := GenerateTempFolder(GetTempFilePath); FTenderTempFolder := FTempFolder + '\Tender'; CreateDirectoryInDeep(FTenderTempFolder); try Result := DecryptFile(AFileName) and CheckFileMatchXml; finally DeleteFileOrFolder(FTempFolder); end; end; function TTenderFileChecker.DecryptFile(const AFileName: string): Boolean; begin Result := UnZipFile(AFileName, FTempFolder); if not Result then Exit; LoadInfo; Result := UnZipFile(FTenderFileName, FTenderTempFolder); end; procedure TTenderFileChecker.LoadInfo; begin LoadInfoFromXml; end; procedure TTenderFileChecker.LoadInfoFromXml; var FXmlDocument: IXMLDocument; XmlNode: IXMLNode; FRootList: IXMLNodeList; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.LoadFromFile(FTempFolder + '\Info.xml'); FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl]; XmlNode := FXmlDocument.DocumentElement; LoadInfoFromXmlDocument(XmlNode); finally FRootList := nil; FXmlDocument := nil; end; end; procedure TTenderFileChecker.LoadInfoFromXmlDocument(AXmlNode: IXMLNode); var ChildNodes: IXMLNodeList; begin ChildNodes := AXmlNode.ChildNodes; LoadProjectInfo(ChildNodes.FindNode('ProjectInfo')); end; procedure TTenderFileChecker.LoadProjectInfo(AXmlNode: IXMLNode); begin FProjectName := AXmlNode.Attributes['ProjectName']; FPhaseCount := AXmlNode.Attributes['PhaseCount']; FAuditStatus := AXmlNode.Attributes['AuditStatus']; FTenderFileName := FTempFolder + '\' + AXmlNode.Attributes['FileName']; end; { TTenderZipCompleteChecker } function TTenderZipCompleteChecker.CheckAllPhase: Boolean; begin Result := Assigned(FProjectData) and FProjectData.CheckPhaseFileComplete; end; function TTenderZipCompleteChecker.CheckFileValid( const AFileName: string): Boolean; begin FFileName := AFileName; FTempFolder := GenerateTempFolder(GetTempFilePath); try case CheckType of zctAllPhase: Result := UnZipFile(AFileName, FTempFolder) and CheckMain and CheckAllPhase; zctLastPhase: Result := UnZipFile(AFileName, FTempFolder) and CheckMain and CheckLastPhase; end; finally if Assigned(FProjectData) then FProjectData.Free; DeleteFileOrFolder(FTempFolder); end; end; function TTenderZipCompleteChecker.CheckLastPhase: Boolean; begin Result := Assigned(FProjectData) and FProjectData.CheckLastPhaseFileExist; end; function TTenderZipCompleteChecker.CheckMain: Boolean; begin Result := False; if FileExists(FTempFolder + '\main.dat') then begin try FProjectData := TProjectData.Create; FProjectData.OpenForSubmit(FFileName); Result := True; except Result := False; end; end; end; constructor TTenderZipCompleteChecker.Create; begin FCheckType := zctAllPhase; end; destructor TTenderZipCompleteChecker.Destroy; begin inherited; end; { TmtfFileView } constructor TmtfFileView.Create(const AFileName: string); begin FFileName := AFileName; FTempFolder := GenerateTempFolder(GetTempFilePath); UnZipFile(FFileName, FTempFolder); LoadXmlInfo; FFileName := FTempFolder + '\' + FTenderFileName; end; destructor TmtfFileView.Destroy; begin DeleteFileOrFolder(FTempFolder); inherited; end; procedure TmtfFileView.LoadInfoFromXmlDocument(AXmlNode: IXMLNode); var ChildNodes: IXMLNodeList; begin ChildNodes := AXmlNode.ChildNodes; LoadProjectInfo(ChildNodes.FindNode('ProjectInfo')); end; procedure TmtfFileView.LoadProjectInfo(AXmlNode: IXMLNode); begin FTenderFileName := AXmlNode.Attributes['FileName']; end; procedure TmtfFileView.LoadXmlInfo; var FXmlDocument: IXMLDocument; XmlNode: IXMLNode; FRootList: IXMLNodeList; begin FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument; try FXmlDocument.LoadFromFile(FTempFolder + '\Info.xml'); FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl]; XmlNode := FXmlDocument.DocumentElement; LoadInfoFromXmlDocument(XmlNode); finally FRootList := nil; FXmlDocument := nil; end; end; end.