From beac355a0f1b5f75020760c36061283e44e9636c Mon Sep 17 00:00:00 2001
From: curtis <curtis@i-mps.com>
Date: 星期二, 24 三月 2026 08:48:20 +0800
Subject: [PATCH] doc
---
doc/curtis/Local_IO_抽像方法列表.md | 0
separate/scanImp/CB_IMGPSScanImp_Utils.pas | 2545 +++++++
.idea/git_toolbox_prj.xml | 15
separate/scanImp/CB_IMGPSScanImp_Scan.pas | 1050 ++
CB_IMGPSScanImp.ts | 694 +
separate/scanImp/CB_IMGPSScanImp_Scan.ts | 124
doc/curtis/Delphi_套件_EnScan_webAssembly_可行性.md | 77
doc/curtis/index.md | 15
separate/scanImp/CB_IMGPSScanImp_Data.pas | 5178 ++++++++++++++
doc/curtis/Scanner_Controller_Analysis.md | 62
CB_IMGPSScan_TLB.ts | 123
.idea/misc.xml | 6
.idea/vcs.xml | 7
doc/curtis/AI可能讀不到的_TLB_介面.md | 44
.idea/modules.xml | 8
doc/curtis/Local_IO_路徑與檔案操作分析.md | 233
doc/curtis/分析_尚進行中.md | 830 ++
doc/curtis/Transport_Manager_Analysis.md | 69
doc/curtis/remote_相關方法.md | 0
doc/curtis/UI_View_Analysis.md | 86
split_pascal.js | 98
doc/curtis/Business_Logic_Analysis.md | 64
separate/scanImp/CB_IMGPSScanImp_UI.ts | 78
doc/curtis/delphi_conventions.md | 249
separate/scanImp/CB_IMGPSScanImp_Data.ts | 819 ++
separate/scanImp/CB_IMGPSScanImp_Main.pas | 1089 +++
doc/curtis/Image_Processer_Analysis.md | 69
.idea/codeStyles | 116
.idea/.gitignore | 8
doc/curtis/OCX_溝通與_抽象層抽換.md | 249
separate/scanImp/CB_IMGPSScanImp_Utils.ts | 59
doc/curtis/ScanImp_源碼分析.md | 242
doc/curtis/Delphi_套件相依.md | 115
separate/scanImp/CB_IMGPSScanImp_Main.ts | 17
separate/scanImp/CB_IMGPSScanImp_UI.pas | 6592 ++++++++++++++++++
35 files changed, 21,030 insertions(+), 0 deletions(-)
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/codeStyles b/.idea/codeStyles
new file mode 100644
index 0000000..dc4aa1e
--- /dev/null
+++ b/.idea/codeStyles
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectCodeStyleConfiguration">
+ <code_scheme name="Project" version="173">
+ <codeStyleSettings language="XML">
+ <arrangement>
+ <rules>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:android</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:id</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>style</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>ANDROID_ATTRIBUTE_ORDER</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>.*</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ </rules>
+ </arrangement>
+ </codeStyleSettings>
+ </code_scheme>
+ </component>
+</project>
diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 0000000..cca44d7
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="GitToolBoxProjectSettings">
+ <option name="commitMessageIssueKeyValidationOverride">
+ <BoolValueOverride>
+ <option name="enabled" value="true" />
+ </BoolValueOverride>
+ </option>
+ <option name="commitMessageValidationEnabledOverride">
+ <BoolValueOverride>
+ <option name="enabled" value="true" />
+ </BoolValueOverride>
+ </option>
+ </component>
+</project>
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..83fb565
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<project version="4">
+ <component name="MarkdownNavigator.ProfileManager" plain-text-search-scope="Project Files" />
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-11" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..3765b7b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/CB_IMGPSScan.iml" filepath="$PROJECT_DIR$/.idea/CB_IMGPSScan.iml" />
+ </modules>
+ </component>
+</project>
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..20620ba
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
+ </component>
+</project>
diff --git a/CB_IMGPSScanImp.ts b/CB_IMGPSScanImp.ts
new file mode 100755
index 0000000..0adddc1
--- /dev/null
+++ b/CB_IMGPSScanImp.ts
@@ -0,0 +1,694 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+// ============================================================================
+// 模擬 Delphi 與 VCL/硬體 相依介面 (Node.js 中不存在的實體)
+// ============================================================================
+export type TObject = any;
+export type TMouseButton = 'mbLeft' | 'mbRight' | 'mbMiddle';
+export type TShiftState = any;
+export type THandle = number;
+export type TDibGraphic = any;
+export type TTiffGraphic = any;
+export type TImageFormat = 'ifBlackWhite' | 'ifGray256' | 'ifTrueColor' | 'ifColor256';
+export type TMouseMode = 'mmUser' | 'mmAmplifier' | 'mmZoom' | 'mmDrag' | 'mmR270' | 'mmR180' | 'mmR90' | 'mmDelete';
+export type TxActiveFormBorderStyle = number;
+export type TxPrintScale = number;
+export type TxPopupMode = number;
+export type OLE_COLOR = number;
+export type IFontDisp = any;
+
+export interface TTreeNode {
+ Text: string;
+ Level: number;
+ ImageIndex: number;
+ SelectedIndex: number;
+ Parent?: TTreeNode;
+ Count: number;
+ Item: TTreeNode[];
+ Expand(expand: boolean): void;
+ Delete(): void;
+}
+
+export interface TImageScrollBox {
+ Name: string;
+ FileName: string;
+ Graphic: any;
+ DisplayedGraphic: any;
+ MouseMode: TMouseMode;
+ ZoomMode: any;
+ ZoomPercent: number;
+ AntiAliased: boolean;
+ Parent: any;
+ LoadFromFile(filename: string, index: number): void;
+ SaveToFile(filename: string): void;
+ Redraw(force: boolean): void;
+ SetFocus(): void;
+ BeginDrag(immediate: boolean): void;
+}
+
+export interface TListView {
+ Items: { Count: number; Item: any[], Add(): any, Clear(): void };
+ Selected: any;
+ ItemIndex: number;
+ ClearSelection(): void;
+ Clear(): void;
+}
+
+export interface TTreeView {
+ Items: { Add(node: any, text: string): TTreeNode; AddChild(node: any, text: string): TTreeNode; Clear(): void };
+ Selected: TTreeNode;
+}
+
+// ============================================================================
+// 模擬 Delphi TStringList 檔案字串處理功能
+// ============================================================================
+export class TStringList {
+ private _strings: string[] = [];
+
+ get Count(): number { return this._strings.length; }
+ get Strings(): string[] { return this._strings; }
+ set Strings(value: string[]) { this._strings = value; }
+ get Text(): string { return this._strings.join('\n'); }
+ set Text(value: string) { this._strings = value.split('\n'); }
+ get CommaText(): string { return this._strings.join(','); }
+ set CommaText(value: string) { this._strings = value.split(','); }
+
+ public Add(item: string) { this._strings.push(item); }
+ public Insert(index: number, item: string) { this._strings.splice(index, 0, item); }
+ public Delete(index: number) { this._strings.splice(index, 1); }
+ public Clear() { this._strings = []; }
+ public IndexOf(item: string): number { return this._strings.indexOf(item); }
+
+ public LoadFromFile(filepath: string) {
+ if (fs.existsSync(filepath)) {
+ const data = fs.readFileSync(filepath, 'utf8');
+ this._strings = data.split(/\r?\n/).filter(line => line.length > 0);
+ }
+ }
+
+ public SaveToFile(filepath: string) {
+ fs.writeFileSync(filepath, this._strings.join('\n'), 'utf8');
+ }
+
+ public Sort() { this._strings.sort(); }
+ public Assign(source: TStringList) { this._strings = [...source.Strings]; }
+}
+
+// ============================================================================
+// 列舉與資料結構
+// ============================================================================
+export enum TTransMode { tsHttp, tsFtp, tsNone }
+export enum TScanMode { smNew, smReplace, smInsert, smSample, smRTS }
+export enum TFtpProtocol { fpftp, fpftps }
+
+export interface TScanInfo {
+ MultiPage: boolean;
+ Graphic: TTiffGraphic;
+ Stream: any;
+ ImageCount: number;
+}
+
+export interface TOMRErrInfo {
+ Display: boolean;
+ Ignore: boolean;
+ Info: string;
+ Mode: string;
+}
+
+export interface TScrollRec {
+ HScroll: number;
+ VScroll: number;
+ Rate: number;
+}
+
+export interface TPoint {
+ X: number;
+ Y: number;
+}
+
+export interface TMpsBarcodeinf {
+ Count: number;
+ Text: string[];
+ r180: number[];
+}
+
+// ============================================================================
+// 主要實作類別 (對應 TCB_IMGPSScanX)
+// ============================================================================
+export class TCB_IMGPSScanX {
+ // ===== 系統全域變數 =====
+ private Ch_WriteNote: boolean = false;
+ private RejectCase: boolean = false;
+ private ErrIndex: number = 0;
+
+ // ===== 預設區 =====
+ private Def_DeviceDelete: boolean = true;
+ private Def_DeviceDeleteSize: number = 3072;
+ private Def_ScannerReverse: boolean = false;
+ private Def_BoardClear: boolean = false;
+ private Def_ScanDpi: number = 300;
+ private Def_ScanDuplex: boolean = true;
+ private Def_ScanRotate: number = 0;
+ private Def_ScanDeskew: boolean = false;
+ private Def_ScanBright: number = 0;
+ private Def_ScanContrast: number = 0;
+ private Def_ScanImgShowMode: number = 2;
+ private Def_ScanImgSetUse: boolean = false;
+
+ // ===== 傳入參數 =====
+ private FUrl: string = '';
+ private FCaseID: string = '';
+ private FMode: string = '';
+ private FModeName: string = '';
+ private FWork_no: string = '';
+ private FUserID: string = '';
+ private FUserName: string = '';
+ private FUserUnit: string = '';
+ private FData: string = '';
+ private FVerify: string = '';
+ private FReWrite: string = '';
+ private FLanguage: string = 'zh_tw';
+ private FLoanDoc_Value: string = '';
+ private FLoanDoc_Enable: string = '';
+ private FUseProxy: string = '';
+ private FC_DocNoList: string = '';
+ private FC_DocNameList: string = '';
+ private FFixFileList: string = '';
+ private FIs_In_Wh: string = '';
+ private FOldCaseInfo: string = '';
+ private FPrintyn: string = '';
+ private FIs_OldCase: string = '';
+ private FCustDocYN: string = '';
+ private FImgDPI: number = 300;
+ private FScanColor: number = 0;
+ private FFileSizeLimit: number = 5120; // 5 * 1024
+ private FCaseNoLength: number = 16;
+ private FImgDelete: string = 'N';
+ private FIsExternal: string = 'N';
+ private FCheck_main_form: string = 'N';
+ private FWH_category: string = 'N';
+
+ // ===== 狀態變數 =====
+ private TransMode: TTransMode = TTransMode.tsNone;
+ private HttpErrStr: string = '';
+ private ScanColor: TImageFormat = 'ifBlackWhite';
+ private ServerDate: string = '';
+ private ServerTime: string = '';
+ private Balance: number = 0;
+ private ScanDenialTime: string = '';
+ private ScanDenialHint: string = '';
+
+ // ===== 路徑區 =====
+ private ScanPath: string = '';
+ private ImagePath: string = '';
+ private ImageSavePath: string = '';
+ private ScaniniPath: string = '';
+ private LngPath: string = '';
+ private CheckXmlPath: string = '';
+ private SitePath: string = '';
+ private SamplePath: string = '';
+ private TransPath: string = '';
+
+ // ===== 清單區 =====
+ private Doc_Inf_List: TStringList = new TStringList();
+ private DM_FORM_INF_List: TStringList = new TStringList();
+ private FORM_INF_List: TStringList = new TStringList();
+ private CHECK_RULE_INF_List: TStringList = new TStringList();
+ private MEMO_INF_List: TStringList = new TStringList();
+ private WORK_INF_List: TStringList = new TStringList();
+ private LASTEST_FORM_INF_List: TStringList = new TStringList();
+ private FindResult: TStringList = new TStringList();
+ private CaseList: TStringList = new TStringList();
+ private Context_DocnoList: TStringList = new TStringList();
+ private CaseDocNoList: TStringList = new TStringList();
+ private CaseDocNo_CopiesList: TStringList = new TStringList();
+ private ContextList: TStringList = new TStringList();
+ private AttContextList: TStringList = new TStringList();
+ private OMRFileList: TStringList = new TStringList();
+ private Cust_DocNoList: TStringList = new TStringList();
+ private IN_WH_DocNoList: TStringList = new TStringList();
+ private FormCode_PageSize: TStringList = new TStringList();
+ private DocNo_NeedDoc: TStringList = new TStringList();
+ private DocNo_NoDoc: TStringList = new TStringList();
+ private DocNo_VerinCase: TStringList = new TStringList();
+ private NoSaveBarCodeList: TStringList = new TStringList();
+ private FormID_List: TStringList = new TStringList();
+ private DocNo_List: TStringList = new TStringList();
+ private NowShowFileList: TStringList = new TStringList();
+ private NowSelectFileList: TStringList = new TStringList();
+ private GuideFormIDList: TStringList = new TStringList();
+ private DivPageFormIDList: TStringList = new TStringList();
+ private LastInitFormidList: TStringList = new TStringList();
+ private LastAddFormidList: TStringList = new TStringList();
+ private SampleFormIDList: TStringList = new TStringList();
+ private ExistImgList: TStringList = new TStringList();
+ private reSizeExistImgList: TStringList = new TStringList();
+
+ // ===== 顯示區變數 =====
+ private NowCaseno: string = '';
+ private NowDocNo: string = '';
+ private NowDocDir: string = '';
+ private NowFormCode: string = '';
+ private NowFormName: string = '';
+ private NowPage: number = 0;
+ private DisplayPath: string = '';
+ private Case_loandoc: string = '';
+
+ // ===== 其他狀態 =====
+ private ScanModeState: TScanMode = TScanMode.smNew;
+ private InitialOk: boolean = false;
+ private ShowText: string = '';
+ private SafePixel: number = 20;
+ private OMRErrInfo: TOMRErrInfo[] = []; // length 11
+
+ // UI Mocks
+ private TreeView1: TTreeView = {} as TTreeView;
+ private PageLV: TListView = {} as TListView;
+ private ISB1: TImageScrollBox = {} as TImageScrollBox;
+ private DisplayISB: TImageScrollBox = {} as TImageScrollBox;
+ private SelectISB: TImageScrollBox = {} as TImageScrollBox;
+ private NewTreeNode: TTreeNode = {} as TTreeNode;
+ private MyTreeNode1: TTreeNode = {} as TTreeNode;
+ private MyTreeNode2: TTreeNode = {} as TTreeNode;
+ private MyTreeNode3: TTreeNode = {} as TTreeNode;
+
+ constructor() {
+ // Constructor initialization
+ }
+
+ // ============================================================================
+ // COM 屬性 (Getters & Setters)
+ // ============================================================================
+ get url(): string { return this.FUrl; }
+ set url(value: string) { this.FUrl = value; }
+
+ get caseid(): string { return this.FCaseID; }
+ set caseid(value: string) { this.FCaseID = value; }
+
+ get mode(): string { return this.FMode; }
+ set mode(value: string) { this.FMode = value.toUpperCase(); }
+
+ get work_no(): string { return this.FWork_no; }
+ set work_no(value: string) { this.FWork_no = value; }
+
+ get userid(): string { return this.FUserID; }
+ set userid(value: string) { this.FUserID = value; }
+
+ get username(): string { return this.FUserName; }
+ set username(value: string) { this.FUserName = value; }
+
+ get userunit(): string { return this.FUserUnit; }
+ set userunit(value: string) { this.FUserUnit = value; }
+
+ get data(): string { return this.FData; }
+ set data(value: string) { this.FData = value; }
+
+ get verify(): string { return this.FVerify; }
+ set verify(value: string) { this.FVerify = value; }
+
+ get rewrite(): string { return this.FReWrite; }
+ set rewrite(value: string) { this.FReWrite = value; }
+
+ get modename(): string { return this.FModeName; }
+ set modename(value: string) { this.FModeName = value; }
+
+ get language(): string { return this.FLanguage; }
+ set language(value: string) { this.FLanguage = value.toLowerCase(); }
+
+ get loandoc_value(): string { return this.FLoanDoc_Value; }
+ set loandoc_value(value: string) { this.FLoanDoc_Value = value; }
+
+ get loandoc_enable(): string { return this.FLoanDoc_Enable; }
+ set loandoc_enable(value: string) { this.FLoanDoc_Enable = value; }
+
+ get c_docnolist(): string { return this.FC_DocNoList; }
+ set c_docnolist(value: string) { this.FC_DocNoList = value; }
+
+ get c_docnamelist(): string { return this.FC_DocNameList; }
+ set c_docnamelist(value: string) { this.FC_DocNameList = value; }
+
+ get is_in_wh(): string { return this.FIs_In_Wh; }
+ set is_in_wh(value: string) { this.FIs_In_Wh = value.toUpperCase(); }
+
+ get oldcaseinfo(): string { return this.FOldCaseInfo; }
+ set oldcaseinfo(value: string) { this.FOldCaseInfo = value; }
+
+ get scancolor(): string { return this.FScanColor.toString(); }
+ set scancolor(value: string) {
+ this.FScanColor = value ? parseInt(value) : 0;
+ this.ScanColor = this.FScanColor === 2 ? 'ifTrueColor' : (this.FScanColor === 1 ? 'ifGray256' : 'ifBlackWhite');
+ }
+
+ get imgdpi(): string { return this.FImgDPI.toString(); }
+ set imgdpi(value: string) {
+ this.FImgDPI = value ? parseInt(value) : 300;
+ this.Def_ScanDpi = this.FImgDPI;
+ }
+
+ get filesizelimit(): string { return this.FFileSizeLimit.toString(); }
+ set filesizelimit(value: string) { this.FFileSizeLimit = value ? parseInt(value) : 5120; }
+
+ get casenolength(): string { return this.FCaseNoLength.toString(); }
+ set casenolength(value: string) { this.FCaseNoLength = value ? parseInt(value) : 0; }
+
+ get WH_CATEGORY(): string { return this.FWH_category; }
+ set WH_CATEGORY(value: string) { this.FWH_category = value; }
+
+ // ============================================================================
+ // 核心資料庫 / 字串解析方法 (移植自 Pascal)
+ // ============================================================================
+
+ /**
+ * 依欄位及索引取值
+ */
+ private GetSQLData(TableList: TStringList, ColName: string, colNo: number): string {
+ if (TableList.Count === 0 || colNo >= TableList.Count) return '';
+
+ const ColStr = TableList.Strings[0].split(',');
+ const TmpStr = TableList.Strings[colNo];
+ const DataStr = TmpStr.split('!@!'); // Delphi 用 '!@!' 分隔
+
+ const idx = ColStr.indexOf(ColName);
+ if (idx !== -1 && idx < DataStr.length) {
+ return DataStr[idx];
+ }
+ return '';
+ }
+
+ /**
+ * 找指定的資料
+ */
+ private FindSQLData(TableList: TStringList, ColumeStr: string, KeyColumeStr: string, KeyStr: string, ColNo: number, ResultList: TStringList): boolean {
+ ResultList.Clear();
+ if (!KeyStr || TableList.Count <= 1) return false;
+
+ const ColList = ColumeStr.split(',');
+ const KeyColList = KeyColumeStr.split(',');
+ const KeyList = KeyStr.split(',');
+
+ let findIndex = -1;
+ let found = false;
+
+ if (ColNo === 0) {
+ for (let i = 1; i < TableList.Count; i++) {
+ let match = true;
+ for (let n = 0; n < KeyColList.length; n++) {
+ const keyCol = KeyColList[n];
+ const keyVal = KeyList[n];
+ if (this.GetSQLData(TableList, keyCol, i) !== keyVal) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ found = true;
+ findIndex = i;
+ break;
+ }
+ }
+ } else {
+ // Specific Row Check
+ let match = true;
+ for (let n = 0; n < KeyColList.length; n++) {
+ const keyCol = KeyColList[n];
+ const keyVal = KeyList[n];
+ const rowData = TableList.Strings[ColNo];
+ if (rowData.indexOf(`!@!${keyVal}!@!`) === -1) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ found = true;
+ findIndex = ColNo;
+ }
+ }
+
+ if (found) {
+ for (let n = 0; n < ColList.length; n++) {
+ const col = ColList[n];
+ ResultList.Add(`${col},${this.GetSQLData(TableList, col, findIndex)}`);
+ }
+ }
+ return found;
+ }
+
+ private GetFindResult(Col: string): string {
+ for (let i = 0; i < this.FindResult.Count; i++) {
+ const s = this.FindResult.Strings[i];
+ const idx = s.indexOf(',');
+ if (idx > -1) {
+ const rCol = s.substring(0, idx);
+ const rValue = s.substring(idx + 1);
+ if (Col === rCol) return rValue;
+ }
+ }
+ return '';
+ }
+
+ // ============================================================================
+ // 文件、表單、名稱轉換方法
+ // ============================================================================
+
+ private FormCode2DocNo(FormCode: string): string {
+ let result = '';
+ for (let i = 0; i < this.FormID_List.Count; i++) {
+ if (this.FormID_List.Strings[i] === FormCode) {
+ result = this.DocNo_List.Strings[i];
+ break;
+ }
+ }
+ if (FormCode && !result) {
+ result = FormCode.substring(0, 8); // 自訂文件
+ }
+ return result;
+ }
+
+ private FormCode2Version(FormCode: string): string {
+ return FormCode.substring(10, 15); // Delphi is 1-based (11,5) -> JS is 0-based (10, 15)
+ }
+
+ private FormCode2Page(FormCode: string): string {
+ return FormCode.substring(8, 10); // Delphi is (9,2)
+ }
+
+ private FileName2FormCode(FileName: string): string {
+ const fname = path.basename(FileName);
+ const v = fname.indexOf('_');
+ const v1 = fname.lastIndexOf('.');
+ if (v > -1 && v1 > v) {
+ return fname.substring(v + 1, v1);
+ }
+ return ''; // 附件
+ }
+
+ private DocNo2DocNoDir(savePath: string, DocNo: string): string {
+ if (DocNo) {
+ let i = 0;
+ let iDocNo = '';
+ do {
+ i++;
+ iDocNo = `${DocNo}(${i})`;
+ } while (fs.existsSync(path.join(savePath, iDocNo)));
+ return iDocNo;
+ }
+ return 'Attach';
+ }
+
+ private DocNoDir2DocNo(DocNoDir: string): string {
+ if (DocNoDir !== 'Attach' && DocNoDir !== 'S_Attach') {
+ const v = DocNoDir.indexOf('(');
+ if (v > 0) return DocNoDir.substring(0, v);
+ return DocNoDir;
+ }
+ return DocNoDir;
+ }
+
+ // ============================================================================
+ // 系統初始化與清單載入 (模擬 Delphi 的 Timer1Timer)
+ // ============================================================================
+ public async InitSystem() {
+ this.InitialOk = false;
+ this.FMaxUploadSize = '10';
+
+ if (!this.FUrl) {
+ console.error('URL cannot be empty, please contact system administrator');
+ return;
+ }
+ if (!this.FUrl.endsWith('/')) this.FUrl += '/';
+
+ // 在 Node.js 中通常依賴環境變數或 config 檔案,這裡模擬建立目錄
+ this.ImagePath = path.join(__dirname, 'Scantemp', this.FWork_no, this.FUserUnit, this.FMode);
+ this.ImageSavePath = this.ImagePath;
+
+ if (!fs.existsSync(this.ImagePath)) fs.mkdirSync(this.ImagePath, { recursive: true });
+
+ this.DataLoading(true, true);
+
+ // TODO: 模擬 HTTP API 請求 (GetServerDate, GetSetInf1~7 等)
+ // await this.GetServerDate();
+ // await this.GetSetInf1();
+
+ this.InitialOk = true;
+ this.DataLoading(false, false);
+ }
+
+ // ============================================================================
+ // 按鈕動作邏輯:上傳 (TransBtnClick)
+ // ============================================================================
+ public async TransBtnClick() {
+ if (!this.InitialOk) {
+ console.log('資訊尚未下載完成,請稍候或重新進入');
+ return;
+ }
+ this.RejectCase = false;
+
+ if (this.NewTreeNode.Count === 0) {
+ console.log('無影像需傳送');
+ return;
+ }
+
+ let SuccessCount = 0;
+ let ReCasecount = 0;
+ let CheckErrCount = 0;
+
+ this.DataLoading(true, true);
+
+ // 巡覽所有案件節點
+ for (let i = 0; i < this.NewTreeNode.Count; i++) {
+ const nodeText = this.NewTreeNode.Item[i].Text;
+ const v = nodeText.indexOf('-');
+ const CaseID = nodeText.substring(0, v);
+
+ this.CreateIn_WH(CaseID);
+ this.Case2upload(CaseID);
+ this.TransPath = path.join(this.ImageSavePath, CaseID, 'Upload');
+
+ // 是否可以上傳?
+ const CaseTrans = this.CaseAsk(CaseID); // 0: 可以, 1: 重複, -1: 失敗
+ if (CaseTrans === -1) {
+ console.error(this.HttpErrStr);
+ this.DataLoading(false, false);
+ return;
+ }
+ if (CaseTrans === 1) {
+ ReCasecount++;
+ continue;
+ }
+
+ if (CaseTrans === 0) {
+ // 進行 OMR 檢核
+ if (this.FMode !== 'FSCAN') {
+ if (!this.OMRCheckCase(CaseID)) {
+ CheckErrCount++;
+ continue;
+ }
+ }
+
+ // 執行傳送 (ZIP 壓縮 + HTTP/FTP Upload)
+ const isTransOk = await this.TransCaseID(this.TransPath, CaseID, true);
+ if (!isTransOk) {
+ this.DataLoading(false, false);
+ return;
+ }
+ SuccessCount++;
+ }
+ }
+
+ this.DataLoading(false, false);
+ console.log(`傳送完成。成功件【${SuccessCount}】件,失敗件【${ReCasecount}】,檢核失敗【${CheckErrCount}】`);
+ }
+
+ // ============================================================================
+ // OMR 檢核邏輯 (OMRCheckCase)
+ // ============================================================================
+ private OMRCheckCase(CaseID: string): boolean {
+ let CaseOk = true;
+ const errIniPath = path.join(this.ImageSavePath, CaseID, 'upload', 'Checkerr.ini');
+ if (fs.existsSync(errIniPath)) fs.unlinkSync(errIniPath);
+
+ const MainFormID = this.GetCaseFormID(path.join(this.ImageSavePath, CaseID, 'upload'));
+
+ // 這裡會實作根據 MainFormID 取得 OMR 檢核 XML 設定的邏輯
+ // 並比對掃描圖檔的影像黑點數量,決定是否缺件或缺漏必填欄位。
+ // TODO: 完整的 OMR Check (XML Parsing and Image Pixel counting)
+
+ return CaseOk;
+ }
+
+ // ============================================================================
+ // 壓縮與傳送封裝 (TransCaseID)
+ // ============================================================================
+ private async TransCaseID(TransPath: string, CaseID: string, MainCase: boolean): Promise<boolean> {
+ // 1. 產生必要的 Data 檔案 (FormCode_Name.dat, DocNo_Name.dat 等)
+ this.CreateFormID_FormName(TransPath, CaseID);
+ this.CreateDocNo_DocName(TransPath, CaseID);
+
+ // 2. 壓縮檔案為 Img.zip (模擬)
+ const zipPath = path.join(TransPath, 'Img.zip');
+ console.log(`[ZIP] Zipping files in ${TransPath} to ${zipPath}`);
+
+ // 3. 檢查檔案大小是否超過限制 FMaxUploadSize
+ // const stat = fs.statSync(zipPath);
+ // if (stat.size > parseInt(this.FMaxUploadSize) * 1048576) { ... }
+
+ // 4. 根據 TransMode 進行 Http POST 或 FTP 上傳
+ if (this.TransMode === TTransMode.tsHttp) {
+ console.log(`[HTTP] Uploading file to ${this.FUrl}...`);
+ // TODO: Axios or fetch POST request
+ } else if (this.TransMode === TTransMode.tsFtp) {
+ console.log(`[FTP] Uploading file to FTP server...`);
+ // TODO: FTP Client put
+ }
+
+ // 5. 刪除本機暫存
+ const caseDir = path.join(this.ImageSavePath, CaseID);
+ if (fs.existsSync(caseDir)) {
+ fs.rmSync(caseDir, { recursive: true, force: true });
+ }
+
+ return true;
+ }
+
+ // ============================================================================
+ // UI 與工具抽象 (Stubbing)
+ // ============================================================================
+ private DataLoading(loading: boolean, useTimer: boolean) {
+ if (loading) {
+ console.log(`Loading... ${this.ShowText}`);
+ } else {
+ console.log('Loading complete.');
+ }
+ }
+
+ private CreateIn_WH(CaseID: string) {
+ // 模擬產生 In_Wh.dat
+ }
+
+ private Case2upload(CaseID: string) {
+ // 模擬搬移/複製檔案結構準備上傳
+ }
+
+ private CaseAsk(CaseID: string): number {
+ // 模擬詢問 Server 案件是否允許上傳
+ return 0; // 0: OK
+ }
+
+ private GetCaseFormID(path: string): string {
+ return '11A000000000000'; // Mock FormID
+ }
+
+ private CreateFormID_FormName(path: string, CaseID: string) {}
+ private CreateDocNo_DocName(path: string, CaseID: string) {}
+
+ private _Msg(msg: string): string {
+ return msg; // 模擬多國語系轉換
+ }
+
+ private Add_Zoo(num: number, length: number): string {
+ let str = num.toString();
+ while (str.length < length) str = '0' + str;
+ return str;
+ }
+}
\ No newline at end of file
diff --git a/CB_IMGPSScan_TLB.ts b/CB_IMGPSScan_TLB.ts
new file mode 100755
index 0000000..01dc53a
--- /dev/null
+++ b/CB_IMGPSScan_TLB.ts
@@ -0,0 +1,123 @@
+// ************************************************************************ //
+// WARNING
+// -------
+// The types declared in this file were converted from a Pascal Type Library.
+// ************************************************************************ //
+
+export const CB_IMGPSScanMajorVersion = 1;
+export const CB_IMGPSScanMinorVersion = 0;
+
+export const LIBID_CB_IMGPSScan = '{F7D1C429-BE85-4FAD-A058-36A41C2AAA89}';
+
+export const IID_ICB_IMGPSScanX = '{E68A01E9-2798-497F-9FB8-4EAFB7CCE5B9}';
+export const DIID_ICB_IMGPSScanXEvents = '{B7FB8B05-8BDA-4DFD-BCCF-2B657E8A108A}';
+export const CLASS_CB_IMGPSScanX = '{8B54EA2A-547C-48AD-BC71-C11C1340B37E}';
+
+export enum TxActiveFormBorderStyle {
+ afbNone = 0x00000000,
+ afbSingle = 0x00000001,
+ afbSunken = 0x00000002,
+ afbRaised = 0x00000003,
+}
+
+export enum TxPrintScale {
+ poNone = 0x00000000,
+ poProportional = 0x00000001,
+ poPrintToFit = 0x00000002,
+}
+
+export enum TxMouseButton {
+ mbLeft = 0x00000000,
+ mbRight = 0x00000001,
+ mbMiddle = 0x00000002,
+}
+
+export enum TxPopupMode {
+ pmNone = 0x00000000,
+ pmAuto = 0x00000001,
+ pmExplicit = 0x00000002,
+}
+
+// OLE_COLOR can be represented as a number
+export type OLE_COLOR = number;
+// IFontDisp can be represented as any for simplicity in Node.js
+export type IFontDisp = any;
+
+export interface ICB_IMGPSScanX {
+ Visible: boolean;
+ AutoScroll: boolean;
+ AutoSize: boolean;
+ AxBorderStyle: TxActiveFormBorderStyle;
+ Caption: string;
+ Color: OLE_COLOR;
+ Font: IFontDisp;
+ KeyPreview: boolean;
+ PixelsPerInch: number;
+ PrintScale: TxPrintScale;
+ Scaled: boolean;
+ readonly Active: boolean;
+ DropTarget: boolean;
+ HelpFile: string;
+ PopupMode: TxPopupMode;
+ ScreenSnap: boolean;
+ SnapBuffer: number;
+ DockSite: boolean;
+ DoubleBuffered: boolean;
+ readonly AlignDisabled: boolean;
+ readonly MouseInClient: boolean;
+ readonly VisibleDockClientCount: number;
+ ParentDoubleBuffered: boolean;
+ UseDockManager: boolean;
+ Enabled: boolean;
+ readonly ExplicitLeft: number;
+ readonly ExplicitTop: number;
+ readonly ExplicitWidth: number;
+ readonly ExplicitHeight: number;
+ AlignWithMargins: boolean;
+ ParentCustomHint: boolean;
+ url: string;
+ caseid: string;
+ mode: string;
+ work_no: string;
+ userid: string;
+ username: string;
+ userunit: string;
+ data: string;
+ verify: string;
+ rewrite: string;
+ modename: string;
+ language: string;
+ loandoc_value: string;
+ loandoc_enable: string;
+ useproxy: string;
+ c_docnolist: string;
+ c_docnamelist: string;
+ fixfilelist: string;
+ is_in_wh: string;
+ oldcaseinfo: string;
+ printyn: string;
+ is_oldcase: string;
+ custdocyn: string;
+ scancolor: string;
+ imgdpi: string;
+ filesizelimit: string;
+ casenolength: string;
+ imgdelete: string;
+ isExternal: string;
+ check_main_form: string;
+ WH_CATEGORY: string;
+}
+
+export interface ICB_IMGPSScanXEvents {
+ OnActivate(): void;
+ OnClick(): void;
+ OnCreate(): void;
+ OnDblClick(): void;
+ OnDestroy(): void;
+ OnDeactivate(): void;
+ OnKeyPress(Key: number): void;
+ OnMouseEnter(): void;
+ OnMouseLeave(): void;
+ OnPaint(): void;
+ OnClosePage(): void;
+}
diff --git "a/doc/curtis/AI\345\217\257\350\203\275\350\256\200\344\270\215\345\210\260\347\232\204_TLB_\344\273\213\351\235\242.md" "b/doc/curtis/AI\345\217\257\350\203\275\350\256\200\344\270\215\345\210\260\347\232\204_TLB_\344\273\213\351\235\242.md"
new file mode 100644
index 0000000..569f6bb
--- /dev/null
+++ "b/doc/curtis/AI\345\217\257\350\203\275\350\256\200\344\270\215\345\210\260\347\232\204_TLB_\344\273\213\351\235\242.md"
@@ -0,0 +1,44 @@
+
+
+
+
+# IO 相關方法
+## Dir
+```Pascal
+function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean;
+function str2Dir(const path: string[]): void
+```
+
+
+## String ini 相關
+```Pascal
+TIniFile = class(TCustomIniFile)
+ public
+ destructor Destroy; override;
+ function ReadString(const Section, Ident, Default: string): string; override;
+ procedure WriteString(const Section, Ident, Value: String); override;
+ procedure ReadSection(const Section: string; Strings: TStrings); override;
+ procedure ReadSections(Strings: TStrings); override;
+ procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
+ procedure EraseSection(const Section: string); override;
+ procedure DeleteKey(const Section, Ident: String); override;
+ procedure UpdateFile; override;
+ end;
+```
+
+
+## String dat 相關
+delphi 大量使用 字串.LoadFromFile, 字串.SaveToFile
+- LoadFromFile
+- SaveToFile
+```Pascal
+procedure LoadFromFile(const FileName: string); overload; virtual;
+procedure LoadFromFile(const FileName: string; Encoding: TEncoding); overload; virtual;
+procedure LoadFromStream(Stream: TStream); overload; virtual;
+procedure LoadFromStream(Stream: TStream; Encoding: TEncoding); overload; virtual;
+procedure Move(CurIndex, NewIndex: Integer); virtual;
+procedure SaveToFile(const FileName: string); overload; virtual;
+procedure SaveToFile(const FileName: string; Encoding: TEncoding); overload; virtual;
+procedure SaveToStream(Stream: TStream); overload; virtual;
+procedure SaveToStream(Stream: TStream; Encoding: TEncoding); overload; virtual;
+```
diff --git a/doc/curtis/Business_Logic_Analysis.md b/doc/curtis/Business_Logic_Analysis.md
new file mode 100644
index 0000000..aa486eb
--- /dev/null
+++ b/doc/curtis/Business_Logic_Analysis.md
@@ -0,0 +1,64 @@
+# 業務邏輯與資料解析模組 (Business Logic & Parser) 深度分析
+
+在 `CB_IMGPSScanImp.pas` 中,「業務邏輯與資料解析模組」扮演了將底層掃描影像與上層銀行/保險業務需求結合的橋樑。它將前端網頁傳入的原始設定資料,轉換為系統可理解的「案件 (Case)」、「文件 (Document)」與「表單 (Form)」結構,並執行極度複雜的業務規則檢核 (OMR 檢核)。
+
+若要將此模組進一步細拆,其內部組成可分為以下四大子分類:
+
+---
+
+## 1. 系統參數與組態儲存庫 (Config & Parameter Repository)
+
+**職責**:負責解析由 Web 端透過字串傳入的各類系統設定表(通常以 `!@!` 等特殊符號分隔),並將其儲存於記憶體中供全局查詢。
+**核心實作特性**:
+* **字串表解析**:大量使用 `TStringList` 作為輕量級的記憶體資料庫 (`SetSQLData`, `GetSQLData`, `FindSQLData`)。
+* **系統設定下載與維護** (`GetSetInf1` ~ `GetSetInf7`):
+ * `DOC_INF`:文件設定檔(定義文件類型、是否需入庫等)。
+ * `FORM_INF`:表單設定檔(定義條碼對應、長寬、十字定位點、最大頁數)。
+ * `DM_FORM_INF`:相依與互斥規則檔。
+ * `CHECK_RULE_INF`:檢核規則錯誤訊息定義檔。
+ * `WORK_INF`:系統與硬體掃描的預設參數。
+
+## 2. 領域實體對映與結構管理器 (Entity Mapping & Structure Manager)
+
+**職責**:將抽象的條碼 (Barcode) 對映至具體的業務實體,並在檔案系統上維護「案件 -> 文件分份 -> 頁面」的實體目錄與虛擬樹狀結構 (`.dat` 索引檔)。
+**核心實作特性**:
+* **條碼解析對映**:`BarCode2FormID`、`BarCode2CaseID`、`FormCode2DocNo`、`DocNo2DocName`。
+* **虛擬檔案系統維護**:
+ * 處理文件是否需要拆分多份 (`DocNoNeedDiv`)。
+ * 管理 `Context.dat`、`CaseDocNo.dat`、`CaseDocNo_Copies.dat` 等索引檔,以記錄掃描影像與業務文件的歸屬關係。
+* **封裝資訊產生器**:`CreateDocNo_Info`、`CreateCustDocNo_Info` (將目錄結構轉換回 Web 端所需的特定字串格式)。
+
+## 3. OMR 與業務規則檢核引擎 (OMR & Business Rule Engine)
+
+**職責**:整個系統最龐大且複雜的業務邏輯核心,負責確保掃描進來的影像完全符合進件規定,防止缺件或矛盾。
+**核心實作特性** (`OMRCheckCase`):
+* **文件級別檢核 (Document-Level Rules)**:
+ * **主文件檢核**:檢查主要文件是否齊全、頁數是否符合資料庫預期。
+ * **相依/互斥檢核**:依據 `DM_FORM_INF`,判斷若存在 A 文件,是否遺漏了必附的 B 文件,或錯誤附上了互斥的 C 文件。
+ * **生命週期檢核**:判斷表單條碼是否已超過停用日期、或超過允許的最大掃描頁數。
+* **OMR 畫記與欄位級別檢核 (Field-Level OMR Rules)** (透過 `Xmltool` 解析 `.xml` 設定檔,並計算指定 `(X, Y)` 座標的黑白像素點 `GetSiteOMR`):
+ * `settype1` (必填檢核):特定的 OMR 區塊必須有畫記。
+ * `settype3` (有值連動必填):A 欄位有畫記時,相關的 B 欄位也必須畫記。
+ * `settype8` (有值連動互斥):A 欄位有畫記時,相關的 B 欄位不能畫記。
+ * `settype4` (有值相依文件):特定欄位有畫記時,系統必須檢查是否已附上指定的文件。
+ * `settype5` (有值互斥文件):特定欄位有畫記時,系統必須檢查不能附上指定的文件。
+ * `settype6` (強制備註):特定欄位有畫記時,要求使用者必須手動輸入備註說明。
+ * `settype7` (OMR 帶值提取):讀取畫記並轉換為特定的業務數值 (`GetValue.xml`),隨後傳回後端。
+
+## 4. 案件異動與舊案引用處理器 (Case Modification & Legacy Handler)
+
+**職責**:處理「補件 (ESCAN)」、「重掃 (RSCAN)」、「引用舊件」等極度複雜的邊界狀態與跨案件資料流動。
+**核心實作特性**:
+* **文件引用管理**:`SetUseCase`、`GetUseCase` 記錄與追蹤不同案件之間文件的借用與引用關係 (記錄於 `UseCase.ini`)。
+* **版本相容與轉換**:`OldCasetoNewCase`、`ErrFormtoCurrentForm` (處理舊系統升級或表單版本更迭時的自動替換邏輯)。
+* **防呆與鎖定**:`DeleteDocNoFileForESCAN` 等邏輯,防止在補件模式下誤刪非當次掃描的既有影像。
+
+---
+
+## 💡 未來重構與微服務化建議
+
+若要將此「業務邏輯模組」進行現代化重構,強烈建議引入以下設計模式:
+
+1. **Repository Pattern (儲存庫模式)**:將目前散落的 `FindSQLData` 與 `TStringList` 查詢,封裝為 `FormConfigRepository`、`DocConfigRepository` 等強型別介面,隔離底層字串處理細節。
+2. **Rule Engine (規則引擎)**:將 `OMRCheckCase` 內部數百行的 `if/else` 與 XML 巡覽,拆分為獨立的實體類別(例如 `RequiredFieldRule`, `DependencyDocumentRule`, `MutexFieldRule`),並透過統一的 `Validator` 介面依序執行,大幅提升可測試性 (Testability) 與維護性。
+3. **Domain Driven Design (領域驅動設計)**:將依賴實體 `.dat` 檔案的狀態管理,重構成記憶體中的 `TCase`, `TDocument`, `TPage` 領域物件,只有在最終儲存或打包時才寫入實體檔案系統。
diff --git "a/doc/curtis/Delphi_\345\245\227\344\273\266_EnScan_webAssembly_\345\217\257\350\241\214\346\200\247.md" "b/doc/curtis/Delphi_\345\245\227\344\273\266_EnScan_webAssembly_\345\217\257\350\241\214\346\200\247.md"
new file mode 100644
index 0000000..493a532
--- /dev/null
+++ "b/doc/curtis/Delphi_\345\245\227\344\273\266_EnScan_webAssembly_\345\217\257\350\241\214\346\200\247.md"
@@ -0,0 +1,77 @@
+
+
+# EnScan 的功能打包成 webAssembly 處理 Scan 是否可行
+
+
+這是一個非常深入的技術架構問題。簡短的回答是:**「直接打包」不可行,但「功能移轉」與「資料對接」是可行的,只是架構需要完全翻轉。**
+
+我們必須從 WebAssembly (Wasm) 的底層本質,來分析為什麼 `EnScan` 與 `DibHandle` 無法直接放入 Wasm:
+
+---
+
+### 1. 為什麼無法將 EnScan 打包成 WebAssembly 進行「掃描」?
+
+**核心障礙:硬體存取與沙盒 (Sandbox) 限制**
+
+* **Wasm 的隔離性:** WebAssembly 運行在瀏覽器的安全沙盒中。它**完全無法**存取你電腦的硬體(如 USB 接口、掃描機)。它甚至看不到你的 C 槽或 Windows 登錄表。
+* **TWAIN 協定限制:** `EnScan` 的核心是封裝 Windows 的 **TWAIN API**。TWAIN 是一個極度依賴作業系統訊息(Window Messages)與本地驅動程式(`.ds` 檔案)的協定。Wasm 無法呼叫 Windows API,也無法載入掃描機的 `.dll` 驅動程式。
+* **VCL 與 WinAPI 依賴:** `EnScan` 是一個 VCL 元件,深層綁定了 Windows 的 GDI(圖形設備介面)。Wasm 並沒有 Windows GDI,它只有一塊線性記憶體(Linear Memory)和 Canvas API。
+
+---
+
+### 2. Wasm 能處理 `DibHandle` 或 `TMemoryStream` 嗎?
+
+這涉及到兩者記憶體模型的完全不相容:
+
+#### **關於 DibHandle (Windows HGLOBAL)**
+* **不可行:** `DibHandle` 本質上是一個 Windows 作業系統核心管理的**記憶體地址代號**。
+* **原因:** Wasm 的記憶體是「封閉的線性陣列」。它無法透過一個 Windows 句柄(Handle)去讀取 Windows 系統層級的記憶體。如果你把 `DibHandle` 傳給 Wasm,Wasm 只會把它看作一個無意義的整數。
+
+#### **關於 TMemoryStream**
+* **有條件可行:** 如果你使用如 **TMS WEB Core** 這類支援 Delphi 語法轉 Wasm 的工具,它們有實作虛擬的 `TMemoryStream`。
+* **本質差異:** * **Delphi Win32 的 `TMemoryStream`**:操作的是實體 RAM。
+ * **Wasm 的 `TMemoryStream`**:操作的是瀏覽器分配給 Wasm 實例的一塊 **`ArrayBuffer`**。
+ * **兩者不通:** 你無法直接將 Win32 的記憶體指針直接「丟進」Wasm 的記憶體空間。
+
+---
+
+### 3. 可行的「現代化」架構建議:混合模式 (Hybrid)
+
+如果你想用 Wasm 處理掃描後的影像,正確的架構應該是:
+
+
+
+#### **第一步:本地端代理 (Local Agent/Service)**
+你仍需要一個小的 Delphi Win32 程式(或 Service)跑在使用者電腦上:
+1. 呼叫 `EnScan` 進行掃描。
+2. 在 `OnAcquire` 中拿到 `DibHandle`。
+3. **關鍵轉化**:在本地端將 `DibHandle` 轉成標準的影像格式(如 **Base64 String** 或 **Uint8Array 二進位流**)。
+
+#### **第二步:通訊橋樑**
+本地程式透過 **WebSocket** 或 **Local HTTP Server (REST)** 將這串二進位資料傳送給瀏覽器。
+
+#### **第三步:Wasm 接收與處理**
+1. 瀏覽器收到二進位流。
+2. 將資料寫入 Wasm 的記憶體(`ArrayBuffer`)。
+3. **這時 Wasm 就可以發揮威力了**:你可以用 Wasm 來做影像分析、條碼辨識、或是用 C++/Rust 編譯出來的高效能演算法進行影像優化。
+
+---
+
+### 4. 總結對照表
+
+| 功能特性 | 原有的 Delphi OCX | 現代 WebAssembly 方案 |
+| :--- | :--- | :--- |
+| **硬體控制 (TWAIN)** | 直接呼叫 (OK) | **無法存取** (需透過本地 Service 轉發) |
+| **記憶體管理** | 使用 Windows Handle (`DibHandle`) | 使用 Wasm 線性記憶體 (`ArrayBuffer`) |
+| **影像處理速度** | 極快 (Native) | 極快 (Wasm 近乎 Native) |
+| **跨瀏覽器支援** | 僅限 IE / Edge IE Mode | **全瀏覽器支援** (Chrome, Safari, Edge) |
+| **安全風險** | 高 (ActiveX 有權限漏洞) | 極高 (沙盒保護) |
+
+### **我的建議:**
+不要嘗試把 `EnScan` 直接「編譯」成 Wasm,那會導致數千個 WinAPI 連結錯誤。
+
+你應該將 **`CB_IMGPSScanImp.pas`** 拆分成兩部分:
+1. **Backend (Win32)**: 只負責掃描與存成檔案/串流。
+2. **Frontend (Wasm/Web)**: 負責顯示 `ImageScrollBox` 的功能、UI 邏輯與上傳伺服器。
+
+**你想了解如何寫一個簡單的 Local Service,讓 Delphi 掃描後把資料傳給網頁嗎?** 這通常是目前銀行系統現代化(去 IE 化)最普遍的作法。
diff --git "a/doc/curtis/Delphi_\345\245\227\344\273\266\347\233\270\344\276\235.md" "b/doc/curtis/Delphi_\345\245\227\344\273\266\347\233\270\344\276\235.md"
new file mode 100644
index 0000000..d343a80
--- /dev/null
+++ "b/doc/curtis/Delphi_\345\245\227\344\273\266\347\233\270\344\276\235.md"
@@ -0,0 +1,115 @@
+# **相依套件分析報告**
+
+本報告針對 ActiveX 元件核心實作檔 CB_IMGPSScanImp.pas 進行功能解構,並分析其與第三方套件的綁定關係,以作為後續維護或現代化升級之參考。
+
+## **壹、 依功能拆分模組與第三方套件綁定分析**
+
+根據原始碼結構,CB_IMGPSScanImp.pas 是一個將介面、硬體、網路與業務邏輯高度耦合的「上帝物件 (God Object)」。若要進行重構或拆件,建議依據以下五個核心模組進行解耦:
+
+### **1. 硬體掃描控制模組 (Scanner Controller)**
+
+- **功能描述**:負責與實體掃描機溝通,處理 TWAIN 介面初始化、設定掃描參數(DPI、色彩、雙面)、觸發掃描指令,以及接收掃描完成的記憶體影像 (DibHandle)。
+- **子模組細分建議**:
+ - **TWAIN 介面封裝 (TWAIN Wrapper)**:專門負責底層 TWAIN 驅動程式的呼叫、狀態機管理與錯誤處理。
+ - **掃描參數管理器 (Scanner Profile Manager)**:負責載入、儲存與套用各類掃描設定 (DPI、對比、亮度、單雙面等)。
+ - **事件與回呼接收器 (Acquisition Event Handler)**:專責處理非同步的 `OnAcquire` 事件,負責將底層 `DibHandle` 安全地轉換為應用程式可用的影像物件,並通知上層模組。
+- **關鍵方法**:initkscan、StatrTwainScan、OnAcquire、PageEnd、PageDone。
+- **第三方套件綁定 (強綁定)**:
+ - 依賴 **Envision Imaging SDK** (EnScan) 進行 TWAIN 驅動控制。
+ - 依賴 EnMisc 處理底層記憶體或雜項運算。
+
+### **2. 影像處理與轉換模組 (Image Processor)**
+
+- **功能描述**:負責對擷取到的原始影像進行後製處理,包括:裁切(如 A3 裁 A4)、去斜 (Deskew)、旋轉、二值化 (轉黑白)、格式轉換 (轉 TIFF/JPEG),以及讀取影像上的條碼。
+- **子模組細分建議**:
+ - **影像幾何變換引擎 (Image Transformation Engine)**:專責處理去斜 (Deskew)、旋轉、縮放與裁切等座標/空間運算。
+ - **色彩與格式處理器 (Color & Format Converter)**:負責二值化、灰階/彩色轉換,以及 TIFF/JPEG 等不同檔案格式的壓縮與編解碼。
+ - **條碼與標記識別器 (Barcode & Marker Recognizer)**:獨立負責分析影像中的條碼內容,或進行 OMR (光學標記辨識) 的初步像素比對。
+ - **OMR 與十字定位點分析器 (OMR & Anchor Analyzer)**:專門為「光學標記辨識 (OMR)」服務,負責找出影像上的基準定位點,並計算特定區域內的黑白像素分佈。
+- **關鍵方法**:ImageReSize_FormID、CheckNeedCrop、DeskewImg、ConvertToBW。
+- **第三方套件綁定 (強綁定)**:
+ - 依賴 **Envision Imaging SDK** (EnTifGr, EnDiGrph) 進行 TIFF (CCITT Group 4) 壓縮與 DIB 物件封裝。
+ - 依賴 **MPS Barcode** (mpsBarco, BarcodesFinder) 進行影像條碼掃描與解析。
+
+### **3. 安全傳輸與 API 通訊模組 (Transport Manager)**
+
+- **功能描述**:負責將掃描並壓縮後的檔案上傳至伺服器,或從伺服器下載檔案。同時處理與後端 Java Servlet 的參數交換(如校時、取得 FTP 資訊、更新案件狀態)。
+- **子模組細分建議**:
+ - **HTTP/HTTPS API 請求管理器 (RESTful / Servlet Client Wrapper)**: 專責透過 HTTP(S) 協定,向後端的 Java Servlet 端點發送 GET/POST 請求。
+ - **雙協定檔案上傳/下載引擎 (Dual-Protocol File Transfer Engine)**: 處理實體影像檔案的實體傳輸,並根據系統設定動態切換 HTTP 或 FTP 協定。
+ - **安全加密與雜湊模組 (Security, Crypto & Hashing Utils)**: 負責資料傳輸前後的加解密運算,以及檔案完整性的 MD5 校驗,確保通訊過程不被竄改。
+ - **傳輸前置準備與封裝器 (Payload Archiver & Preparer)**: 在真正啟動傳輸前,將硬碟上散落的 TIFF/JPG 檔案、`.dat` 索引檔打包成單一的 ZIP 封裝檔。
+- **關鍵方法**:upFile、dnFile_Get、ProcessServlet_Get、GetServerDate、GetftpInfo。
+- **第三方套件綁定 (強綁定)**:
+ - 依賴 **SecureBlackbox** (SBSimpleSSL, SBHTTPSClient, SBSimpleFTPS 等) 處理 HTTPS/FTPS 安全加密通訊。
+ - 依賴 **Indy** (IdHashMessageDigest) 產生檔案的 MD5 檢核碼。
+ - 依賴自訂/第三方加密庫 (Encryp) 處理字串加解密。
+
+### **4. 業務邏輯與資料解析模組 (Business Logic & Parser)**
+
+- **功能描述**:專案核心的領域邏輯,包含接收網頁端傳入的參數字串進行解析、定義文件歸類邏輯(由條碼推導文件類型)、OMR (光學標記辨識) 檢核定義等。
+- **子模組細分建議**:
+ - **系統參數與組態儲存庫 (Config & Parameter Repository)**:負責解析由 Web 端透過字串傳入的各類系統設定表(如 DOC_INF、FORM_INF 等),並將其儲存於記憶體中供全局查詢。
+ - **領域實體對映與結構管理器 (Entity Mapping & Structure Manager)**:將抽象的條碼對映至具體的業務實體,並在檔案系統上維護「案件 -> 文件分份 -> 頁面」的虛擬樹狀結構。
+ - **OMR 與業務規則檢核引擎 (OMR & Business Rule Engine)**:處理最核心的檢核邏輯,包含主文件/相依互斥文件檢核、欄位級別的 OMR 畫記檢核,以及基於 XML 設定的各種業務規則。
+ - **案件異動與舊案引用處理器 (Case Modification & Legacy Handler)**:專責處理「補件」、「重掃」、「引用舊件」等複雜的邊界狀態與跨案件資料流動。
+- **關鍵方法**:SetSQLData、GetSQLData、FormCode2DocNo、OMRCheckCase。
+- **第三方套件綁定 (中度綁定)**:
+ - 依賴 **Xmltool** 解析 XML 格式的 OMR 座標定義。
+ - 依賴 **VCLZip** (VCLZip, VCLUnZip) 將多個影像檔打包成 ZIP 進行單一傳輸。
+
+### **5. UI 與介面呈現模組 (UI View)**
+
+- **功能描述**:負責 ActiveX 控制項的視覺化介面,包含左側的樹狀文件清單 (TreeView)、右側的影像預覽區 (ScrollBox),以及按鈕與多國語言切換。
+- **子模組細分建議**:
+ - **案件樹狀檢視元件 (TreeView UI)**: 獨立管理左側的案件與文件節點,負責節點的建立、刪除與圖示切換。
+ - **多影像滾動視窗 (ScrollBox View)**: 管理右側大圖及縮圖的並排顯示,支援拖拉、選取以及快捷鍵操作。
+ - **多國語系引擎 (I18N Manager)**: 統一從設定檔中載入字串,替換畫面上所有的 Label、Button 與 Message 提示。
+ - **核心版面與容器管理 (Layout & Container Management)**: 定義整個 ActiveX 控制項的視覺區塊,並透過階層式的 Panel 進行排版管理。
+ - **系統狀態與進度回饋 (Status & Progress Feedback)**: 在進行耗時的任務時,鎖定 UI 並給予使用者明確的等待提示。
+- **關鍵方法**:InitialLanguage、各類 OnClick 事件。
+- **第三方套件綁定 (輕度綁定)**:
+ - 依賴 **Envision Imaging** (EnImgScr) 作為支援大影像拖曳的滾動視窗。
+ - 依賴 PJMenuSpeedButtons 作為自訂外觀的按鈕元件。
+
+## **貳、 第三方套件功能總覽**
+
+為達成上述複雜的業務需求,本專案引入了多個 Delphi 著名的第三方套件。以下為各套件的大致功能說明:
+
+### **1. Envision Imaging SDK (前綴 En)**
+
+這是一套專為 Delphi 設計的高效能影像與 TWAIN 處理套件,在金融與保險業的文件電子化系統中非常常見。
+
+- **EnScan**:封裝了 TWAIN 協定,讓程式能直接控制實體掃描機,控制進紙、解析度與雙面掃描。
+- **EnDiGrph (TDibGraphic)**:封裝 Windows 底層的 DIB (Device Independent Bitmap) 記憶體句柄,讓開發者能像操作一般圖片一樣操作掃描出來的原始資料。
+- **EnTifGr**:專門處理 TIFF 影像格式。銀行業愛用 TIFF 是因為它支援「多頁」且黑白壓縮率極高 (Group 4 Fax Compression)。
+- **EnImgScr**:提供 TImageScrollBox 視覺元件,用來平滑顯示並縮放超大尺寸的掃描圖檔。
+- **EnMisc**:提供影像處理所需的底層輔助數學或資料轉換函式。
+
+### **2. SecureBlackbox (前綴 SB)**
+
+由 EldoS (後被 /n software 收購) 開發的強大安全通訊與加密套件。由於早期 Delphi (D7~D2007) 內建網路庫缺乏完善的 SSL/TLS 支援,此套件被廣泛用於補強安全性。
+
+- **SBHTTPSClient / SBSimpleSSL**:實作了完整的 HTTPS 用戶端通訊協定,用來安全地上傳檔案或呼叫 Servlet API。
+- **SBSimpleFTPS**:支援 FTP over SSL (FTPS) 的安全檔案傳輸。
+- **SBWinCertStorage / SBX509**:處理 Windows 系統內的憑證儲存區,以及 X.509 數位憑證的驗證(例如確認銀行伺服器的 HTTPS 憑證是否合法)。
+
+### **3. MPS Barcode & BarcodesFinder**
+
+- **功能**:這是一套條碼識別引擎。
+- **專案應用**:在掃描過程中(如 PageDone 或 OnAcquire 階段),它會掃描圖片特定區域尋找一維或二維條碼。讀取到的條碼值會被用來決定這張影像屬於哪一種「文件表單」(FormCode),進而實現自動分類歸檔。
+
+### **4. VCLZip (VCLZip, VCLUnZip)**
+
+- **功能**:老牌的 Delphi ZIP 壓縮元件。
+- **專案應用**:為了節省網路頻寬與減少伺服器連線次數,掃描完成的多張 TIFF/JPG 檔案會被打包成一個 .zip 檔後,再一次性上傳至伺服器。
+
+### **5. Indy Components (前綴 Id)**
+
+- **IdHashMessageDigest / idHash**:Delphi 內建的 Internet Direct (Indy) 函式庫。
+- **專案應用**:在此專案中被用來計算檔案或字串的 **MD5 Hash (雜湊值)**。通常用於確保檔案上傳過程沒有損壞,伺服器比對 MD5 一致才算上傳成功。
+
+### **6. 其他工具 (Tools & Utils)**
+
+- **Xmltool**:負責讀寫 XML 檔案。銀行經常將表單的 OMR (光學標記辨識) 檢核座標或參數寫成 XML 設定檔,透過此工具讀入系統。
+- **Encryp**:這可能是開發商自訂或第三方的輕量級加密單元,用來加密本機設定檔 (.ini) 內的敏感資訊或混淆網頁傳入的參數。
diff --git a/doc/curtis/Image_Processer_Analysis.md b/doc/curtis/Image_Processer_Analysis.md
new file mode 100644
index 0000000..41e6b3a
--- /dev/null
+++ b/doc/curtis/Image_Processer_Analysis.md
@@ -0,0 +1,69 @@
+# 影像處理與轉換模組 (Image Processor) 深度分析
+
+在 `CB_IMGPSScanImp.pas` 中,「影像處理與轉換模組」負責在硬體掃描取得原始影像後,以及上傳/顯示之前,對影像進行一系列的強化、分析與格式轉換。這個模組是決定影像品質、檔案大小與後續 OMR 辨識準確率的關鍵。
+
+若要將此模組進一步細拆,其內部組成可分為以下四大子分類:
+
+---
+
+## 1. 影像幾何與物理變換引擎 (Image Geometric Transformation Engine)
+
+**職責**:專責處理影像的空間座標轉換、旋轉、去斜以及裁切,確保最終儲存的影像端正且符合業務規定的尺寸。
+**核心實作特性**:
+* **影像去斜與轉正**:
+ * `DeskewImg`:透過演算法自動偵測影像傾斜角度並將其校正。
+ * `Rotate`:依據條碼辨識出的角度 (`MpsBarcodeinf.r180`) 或使用者手動點擊按鈕 (`SpeedButton14Click` 等),進行 90、180、270 度的旋轉。
+* **影像裁切與分割**:
+ * `CheckNeedCrop`:根據影像寬高比與偵測到的條碼數量,判斷是否為需要分割的 A3 雙頁合併影像。
+ * `CropImg`:給定 `TRect` 座標,將 A3 影像精準裁切為兩張 A4 (`iGraphic_First`, `iGraphic_sec`)。
+* **影像縮放 (Resize)**:
+ * `ImageReSize_FormID` / `ImageReSize_tmp`:依據表單定義檔 (`FORM_INF`) 中的長寬設定與尋找到的十字定位點,強制將影像縮放變形至標準尺寸,以利後續的 OMR 座標對位。
+ * `DpiResize`:調整影像的 DPI 解析度參數。
+
+## 2. 色彩處理與編碼轉換器 (Color & Format Converter)
+
+**職責**:處理影像的色彩深度 (位元深度) 轉換,以及針對不同色彩模式套用最適合的檔案壓縮演算法,以達到最佳的畫質與檔案大小平衡。
+**核心實作特性**:
+* **色彩空間轉換**:
+ * `ConvertToBW`:將彩色或灰階影像強制二值化 (Binarization) 轉為黑白影像,這不僅能大幅縮小檔案,也是條碼與 OMR 辨識的必要前置步驟 (系統通常會保留一個隱藏的 `ISB_BW` 物件專做辨識用)。
+ * `ConvertToGray`:將彩色轉換為灰階 (`ifGray256`)。
+ * `Image_Smooth` / `NegativeImg` / `CleanupBorder`:影像平滑化、反相處理與清除黑邊。
+* **格式與壓縮決策**:
+ * 針對黑白影像 (`ifBlackWhite`):使用 `tcGroup4` (CCITT Group 4 Fax Compression) 或 `tcPackBits` 壓縮,並儲存為 `.tif`。
+ * 針對彩色/灰階影像 (`ifTrueColor`, `ifGray256`, `ifColor256`):轉換為 `TJpegGraphic`,套用 `tcJpeg` 壓縮與指定的壓縮率 (`FJpgCompression` / `SaveQuality`),並儲存為 `.jpg`。
+
+## 3. 條碼識別與解析器 (Barcode Recognizer)
+
+**職責**:獨立負責掃描與解析影像上的一維或二維條碼,這是系統實現「文件自動歸類」的核心依賴。
+**核心實作特性**:
+* **條碼引擎呼叫**:
+ * `MpsGetBarcode`:呼叫底層的 MPS Barcode 引擎,傳入二值化的影像 (`ISB_BW.Graphic`)。
+ * 回傳 `TMpsBarcodeinf` 結構,包含條碼內容字串陣列 (`Text`) 與每個條碼的方向資訊 (`r180`)。
+* **應用與邏輯綁定**:
+ * 透過條碼字串找出對應的 `FormID` 與 `DocNo`。
+ * 檢查條碼長度是否符合規範 (`FormIDLength`),過濾雜訊或誤判的條碼。
+
+## 4. OMR 與十字定位點分析器 (OMR & Anchor Analyzer)
+
+**職責**:專門為「光學標記辨識 (OMR)」服務,負責找出影像上的基準定位點,並計算特定區域內的黑白像素分佈。
+**核心實作特性**:
+* **基準點尋找 (Anchor Finding)**:
+ * `FindPoint`:根據 XML 定義的模式 (`ANCHOR` 或 `FRAME`),在影像四個角落尋找定位基準點 (`UpLPoint`, `UpRPoint`, `DownLPoint`, `DownRPoint`)。
+ * `CheckSize`:比對找到的定位點距離與標準長寬是否有巨大落差,若找不到則記錄至 `AnchorError.dat`。
+* **像素計算與標記判定 (Pixel Calculation)**:
+ * `GetSiteOMR`:根據 XML 傳入的相對座標字串 (`Site`),將其換算為實際的 `TRect`。
+ * `Get_OMR`:計算該區域內黑色像素的數量。
+ * 結合雜訊過濾 (`ClearLine`) 與容差值 (`SafePixel`, `bt`),最終判定該 OMR 欄位是否「有畫記」。
+
+---
+
+## 💡 未來重構與微服務化建議
+
+若要對此影像處理模組進行重構,建議方向如下:
+
+1. **抽離為獨立的 Pipeline 模式 (管線模式)**:
+ 目前這些功能散落在 `OnAcquire` 與各個事件中。應將其重構為一條清晰的影像處理管線:`Image -> Deskew -> Crop -> ConvertBW -> BarcodeRead -> Resize -> Compress -> Save`。每個步驟 (Step) 應該是獨立的類別,方便抽換或開關。
+2. **解耦 UI 與影像處理**:
+ 目前大量依賴畫面上隱藏的 `ISB_BW` (TImageScrollBox) 來進行二值化和條碼辨識。這違反了 MVC 原則且耗費額外的 GDI 資源。應改用純記憶體物件 (如獨立的 `TDibGraphic` 或 `TBitmap`) 在背景執行緒中進行這些運算,不要綁定可見的 UI 元件。
+3. **引入更現代的影像引擎 (如 OpenCV)**:
+ 早期依賴的 Envision SDK 在尋找十字定位點 (FindPoint) 和去斜 (DeskewImg) 的演算法可能較為老舊。若未來轉型為微服務架構,可將這部分邏輯移植為 Python/C++ 並使用 OpenCV 來達成更精準的高速運算。
diff --git "a/doc/curtis/Local_IO_\346\212\275\345\203\217\346\226\271\346\263\225\345\210\227\350\241\250.md" "b/doc/curtis/Local_IO_\346\212\275\345\203\217\346\226\271\346\263\225\345\210\227\350\241\250.md"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/doc/curtis/Local_IO_\346\212\275\345\203\217\346\226\271\346\263\225\345\210\227\350\241\250.md"
diff --git "a/doc/curtis/Local_IO_\350\267\257\345\276\221\350\210\207\346\252\224\346\241\210\346\223\215\344\275\234\345\210\206\346\236\220.md" "b/doc/curtis/Local_IO_\350\267\257\345\276\221\350\210\207\346\252\224\346\241\210\346\223\215\344\275\234\345\210\206\346\236\220.md"
new file mode 100644
index 0000000..51ca802
--- /dev/null
+++ "b/doc/curtis/Local_IO_\350\267\257\345\276\221\350\210\207\346\252\224\346\241\210\346\223\215\344\275\234\345\210\206\346\236\220.md"
@@ -0,0 +1,233 @@
+# **IO 路徑與檔案操作分析**
+
+本報告詳列了 CB_IMGPSScanImp.pas 檔案中定義的所有 IO 相關變數,以及執行目錄與檔案管理的關鍵方法,並定義了抽像化所需的介面原型。
+
+## **壹、 關鍵路徑與檔案變數 (Variables)**
+
+程式中定義了多個全域或私有欄位,用來追蹤檔案在硬碟上的實體位置。
+
+### **1. 核心路徑變數與動態組合邏輯**
+
+| **變數名稱** | **類型** | **組合邏輯 (Combination Logic)** | **用途說明** |
+| --- | --- | --- | --- |
+| **ImagePath** | String | WORK_INF 的 LOCAL_PATH 參數值 | **本機基礎根路徑**。所有暫存資料的起點。 |
+| **ScaniniPath** | String | ImagePath + FWork_No + '\' + FUserUnit + '\' | **設定檔存放區**。區分作業別與單位。 |
+| **ImageSavePath** | String | 同 ImagePath (初期) 或隨 FMode 變動 | **影像儲存基準路徑**。 |
+| **ScanPath** | String | ImageSavePath + ScanCaseno + '\' + ScanDocdir + '\' | **當前掃描實體目錄**。指向最末層的影像資料夾。 |
+| **TransPath** | String | ImageSavePath + CaseID + '\Upload\' | **準備上傳區**。在傳送前將檔案結構扁平化組合於此。 |
+| **DisplayPath** | String | ImageSavePath + NowCaseNo + '\' | **預覽基準目錄**。用於 UI 點選樹狀圖時讀取特定案件資料。 |
+| **LngPath** | String | GetLocalAppDir(Handle) + 'MPS\CB_IMGPS\' | **應用程式資源路徑**。存放在使用者設定檔目錄以避開權限問題。 |
+| **CheckXmlPath** | String | ImagePath + 'OMRSITE\' | **OMR 規則暫存區**。存放從伺服器同步下來的 XML 定義。 |
+| **SamplePath** | String | ImagePath + 'Sample\' + FWork_No + '\' | **範本影像存放區**。按作業別區分。 |
+| **SitePath** | String | ImagePath + 'Site\' | **登打定位存放區**。 |
+| **FFtpRootPath** | String | 透過伺服器回傳值動態設定 | **FTP 伺服器根路徑**。指定在遠端 FTP 伺育器上存放影像檔的起始位址。 |
+
+### **2. 檔案名稱變數 (Filenames)**
+
+| **變數名稱** | **類型** | **用途說明** |
+| --- | --- | --- |
+| **ScanSaveFilename** | String | 下一張掃描影像預定的檔名(通常包含 FormID)。 |
+| **PEFileName** | String | 在 PageEnd 階段確定的最終完整檔案路徑。 |
+| **AttName** | String | **附件目錄名稱**。根據 FIs_In_Wh 決定為 Attach 或 S_Attach。 |
+| **Ext** | String | 副檔名。預設為 .tif,彩色/灰階模式下可能切換為 .jpg。 |
+
+## **貳、 關鍵 IO 操作方法 (Methods)**
+
+以下為需要進行抽像化設計的核心 IO 方法。
+
+### **1. 目錄管理 (Directory Management)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| _DelTree | 遞迴刪除整個目錄樹 | 上傳成功後清空暫存、模式切換初始化目錄 | RemoveDirRecursive(Path) |
+| Str2Dir / ForceDirectories | 確保路徑以 \ 結尾並建立路徑 | 初始化或掃描前建立資料夾 | EnsureDirExists(Path) |
+| GetNoNameCase | 搜尋尚未配號的臨時目錄 | 在本機搜尋如 未配號0001 到 9999 的可用路徑 | FindNextAvailablePath(Pattern) |
+| GetLocalAppDir | 取得 Windows %LocalAppData% 路徑 | 確保在現代 Windows 系統中有權限寫入語言檔與 Log | GetBaseStoragePath() |
+
+### **2. 存在性檢查與搜尋 (Existence & Search)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| FileExists | 檢查指定路徑檔案是否存在 | 在載入 .dat、.ini 或影像前進行安全檢查 | IsFilePresent(Path) |
+| DirectoryExists | 檢查指定路徑資料夾是否存在 | 在建立掃描目錄或上傳前確認結構完整性 | IsDirPresent(Path) |
+| FindFirst / FindNext | 搜尋符合特定格式的檔案 | 取得實體檔案大小 (FileRec.Size) 或遞迴搜尋檔案 | ListFiles(Path, Pattern) / GetFileInfo(Path) |
+
+### **3. 檔案生命週期與刪除 (File Lifecycle & Deletion)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| ReSortFileName | 影像重新編序命名 | 刪除或插入影像後,修正 001_xxx 等序號連續性 | RenameFile(Old, New) |
+| DeleteImageFile | 刪除實體影像檔 | 單張影像刪除並觸發 .dat 內容同步更新 | DeleteFile(Path) |
+| DeleteDocNoFile | 刪除特定文件代號下所有影像 | 整批文件(DocNo)的物理刪除與序號重整 | DeleteFilesByPattern(Pattern) |
+| DeleteShowFile | 刪除 UI 顯示中的影像清單 | 根據介面選取狀態進行批次物理刪除 | DeleteFileList(List<Path>) |
+| RenameFile / MoveFile | 檔案搬移或更名 | 用於「分案」、「移動頁數」或「變更歸類」 | MoveFile(Src, Dest) |
+| CopyFile | 複製實體檔案 | 影像搬移至上傳區或引用舊案件影像 | CopyFile(Src, Dest) |
+
+### **4. 資料紀錄與序列化 (Metadata IO)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| DeleteCustomDocDir | 移除自訂文件定義 | 從 CustomDocNo.ini 中移除特定自訂文件的節點 | Storage.IniDeleteSection(Section) |
+
+### **5. 網路傳輸 IO 方法 (Network Retrieval - dnFile_Get)**
+
+專案中使用 `dnFile_Get` 從伺服器端同步必要的環境檔案或規則定義。
+
+| **抓取對象 (目標路徑)** | **遠端請求 Action** | **用途說明** | |
+| --- | --- | --- | --- |
+| **CheckXmlPath + filename** | `GetCheckXml` | **下載 OMR 檢核定義檔**。同步伺服器端最新的 XML 座標規則,用於自動判斷影像區域。 | https |
+| **SamplePath + filename** | `GetSampleImg` | **下載範本影像**。用於在 UI 介面上提供給操作員對照的標準範例圖檔。 | https |
+| **SitePath + filename** | `GetSiteImg` | **下載定位定義圖**。下載與登打、校對位置相關的輔助影像。 | https |
+| **LngPath + 'Language.ini'** | `GetLanguage` | **同步多國語言檔**。確保用戶端介面文字(繁體、英文、越南語等)與伺服器同步。 | https |
+
+## **參、 資料紀錄與序列化 (Metadata IO)**
+
+專案中使用了大量的 .dat 與 .ini 檔案來記錄目錄內的結構資訊與使用者偏好。
+
+### **1. .dat 檔案 (結構紀錄)**
+
+| **檔案名稱** | **組合路徑邏輯 (Path Logic)** | **內容與用途** |
+| --- | --- | --- |
+| **Context.dat** | ImageSavePath + CaseID + '\' + DocDir + '\Context.dat' | **影像清單**。紀錄該資料夾內所有影像檔名的正確順序。 |
+| **DocDir.dat** | ImageSavePath + CaseID + '\Upload\DocDir.dat' | **目錄對應表**。紀錄 Upload 下每個檔名所屬的原始 DocDir |
+| **CaseDocNo.dat** | ImageSavePath + CaseID + '\CaseDocNo.dat' | **文件目錄索引**。紀錄案件內已建立的實體資料夾名稱。 |
+| **CaseDocNo_Copies.dat** | ImageSavePath + CaseID + '\CaseDocNo_Copies.dat' | **份數紀錄**。對應 CaseDocNo.dat 中的資料夾分別有多少份。 |
+| **CaseIndex.dat** | ImageSavePath + CaseID + '\CaseIndex.dat' | **案件屬性**。如是否為「授信卷」(Case_loandoc)。 |
+| **EditedDocDir.dat** | ImageSavePath + CaseID + '\EditedDocDir.dat' | **異動清單**。紀錄當次操作中被修改過的文件目錄。 |
+| **Scan_Memo.dat** | DisplayPath + 'Scan_Memo.dat' | **使用者註記**。紀錄操作員手動輸入的備註內容。 |
+| **CaseList.dat** | ImageSavePath + 'CaseList.dat' | **案件總表**。紀錄目前本機快取中存在的所有 CaseID。 |
+
+### **2. .ini 檔案 (設定與偏好)**
+
+| **檔案名稱** | **路徑邏輯** | **回寫 (Write-back)** | **內容與用途** | 寫入關聯 |
+| --- | --- | --- | --- | --- |
+| **Scan.ini** | ScaniniPath + 'Scan.ini' | **是 (頻繁)** | **掃描器硬體設定**。儲存最後一次選取的 DPI、雙面、色彩模式、亮度、對比等參數。 | |
+| **CustomDocNo.ini** | ScaniniPath + 'CustomDocNo.ini' | **是 (中等)** | **自訂文件代號**。儲存操作員定義的文件分類名稱與內部 ID 映射。 | DeleteCustomDocDir |
+| **CB_IMGPSScan.ini** | LngPath + 'CB_IMGPSScan.ini' | **是 (低頻)** | **環境配置**。儲存伺服器 IP、Port、自動更新版本資訊等全域參數。 | |
+| **Language.ini** | LngPath + 'Language.ini' | **否 (唯讀同步)** | **多國語言包**。僅透過 `dnFile_Get` 從伺服器抓取更新,OCX 不自行修改。 | |
+
+## **肆、 串流與讀寫操作 (Stream & File I/O)**
+
+源碼中頻繁使用 .LoadFromFile 與 .SaveToFile 來實現資料的持久化。
+
+### **1. 使用 TStringList 讀寫 .dat 結構**
+
+| **操作對象** | **讀取場景 (Load)** | **寫入場景 (Save)** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| **結構清單 (.dat)** | LoadImgFile 載入以重建樹狀結構 | PageEnd 掃描完成或結構增刪後即時存檔 | ReadTextFile(Path) / WriteTextFile(Path, Content) |
+| **備註文件 (Memo)** | 進入備註編輯器時載入舊有內容 | WNoteBtnClick 完成編輯後儲存內容 | ReadTextFile(Path) / WriteTextFile(Path, Content) |
+| **上傳包定義** | N/A | CreateFormID_FormName 產生上傳包所需的定義檔 | WriteTextFile(Path, Content) |
+| | | | |
+| | | | |
+
+### **2. 使用 TImageScrollBox / TDibGraphic 讀寫影像**
+
+| **操作對象** | **讀取場景 (Load)** | **寫入場景 (Save)** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| **掃描影像原始檔** | view_image_... 載入顯示於預覽窗 | OnAcquire 將記憶體影像 (Dib) 持久化至磁碟 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+| **影像處理覆蓋** | ImageReSize_FormID 讀取進行定位縮放 | 處理完成後覆蓋原始影像檔 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+| **旋轉/後製處理** | 點擊旋轉按鈕後從磁碟重新讀取 | 旋轉完成後保存更新內容回實體檔案 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+
+## **伍、 檔案路徑構造邏輯示例**
+
+程式中典型的路徑構造方式如下(以 PageEnd 為例):
+
+// 1. 基礎路徑
+
+ScanPath := ImageSavePath + ScanCaseno + '\';
+
+// 2. 進入特定文件目錄 (DocDir)
+
+ScanPath := ScanPath + ScanDocdir + '\';
+
+// 3. 確保實體目錄存在
+
+Str2Dir(ScanPath);
+
+// 4. 構造最終影像路徑
+
+PEFileName := ScanPath + Add_Zoo(PageCount, 3) + '_' + FormID + ext;
+
+## **陸、 IO 方法具體實作邏輯細部說明 (Detailed Implementation Logic)**
+
+本節針對 CB_IMGPSScanImp.pas 內部如何透過 Windows API 實作這些 IO 操作進行細部解說。
+
+### **1. Str2Dir(Path: string) 的運作機制**
+
+這個方法的主要作用是 **「路徑標準化與實體資料夾建立」**。
+
+- **字串處理**:它會先檢查傳入的 Path 字串最後一個字元是否為 \。如果不是,會自動補上。
+- **建立資料夾**:**是的,它會在內部建立資料夾**。它會呼叫 Delphi 的 ForceDirectories(Path) 函式。
+- **ForceDirectories 的特性**:與一般的 CreateDir 不同,ForceDirectories 會「遞迴」建立路徑中所有不存在的父目錄(例如若路徑為 C:\A\B\C,即使 A 和 B 都不存在,它也會一併建立)。
+
+### **2. _DelTree(DirName: string) 的遞迴邏輯**
+
+由於 Delphi 早期版本沒有提供單一函式來刪除包含檔案的資料夾,此方法透過 Windows 的搜尋機制實現:
+
+- **遍歷搜尋**:使用 FindFirst 和 FindNext 找出資料夾內的所有物件。
+- **檔案處理**:若搜尋到的是一般檔案,直接呼叫 DeleteFile。
+- **遞迴處理**:若搜尋到的是子資料夾,則「自己呼叫自己」 (_DelTree) 先清空該子資料夾。
+- **物理移除**:當資料夾內的所有內容都清空後,呼叫 RemoveDir 將空的資料夾從磁碟移除。
+
+### **3. FindFirst 與 FindNext 的搜尋與疊代邏輯**
+
+這兩個方法是 Delphi 處理「集合式 IO 操作」(如掃描目錄、批次刪除)的基礎,通常搭配 TSearchRec 結構使用。
+
+- **FindFirst(Path, Attr, SearchRec)**:
+- **動作**:啟動搜尋任務,將找到的第一個檔案資訊填入 SearchRec。
+- **應用例**:在 PM104Click (匯入影像) 時,程式會先執行 FindFirst(FName, faAnyfile, FileRec) 來確認使用者選取的實體檔案是否存在,並藉由 FileRec.Size 取得位元組大小,用以判斷是否超過系統設定的匯入限制(例如 5MB)。
+- **FindNext(SearchRec)**:
+- **動作**:繼續尋找下一個符合條件的檔案。
+- **疊代模式**:通常包裹在 repeat ... until FindNext(SR) <> 0 迴圈中。
+- **應用例**:在 _DelTree 實作中,程式利用此疊代邏輯將資料夾內「所有的」子目錄與檔案清空,直到 FindNext 回傳非零值(代表搜尋結束)。
+- **FindClose(SearchRec)**:
+- **重要性**:釋放搜尋控制代碼(Handle)。若未呼叫,頻繁搜尋會導致系統資源洩漏。
+
+### **4. GetNoNameCase(Path: string) 的搜尋邏輯**
+
+這是一個典型的 **「可用名稱查表」** 實作:
+
+- **迴圈範圍**:從 1 迭代到 9999。
+- **格式組合**:使用 Add_Zoo 函式將數字轉為四位數(如 0001),並加上前綴字「未配號」。
+- **磁碟檢查**:呼叫 DirectoryExists 檢查 Path + '未配號000x'。
+- **結果回傳**:第一個回傳 False(代表該資料夾尚不存在)的名稱即為結果,程式會立即跳出迴圈並選定此名稱。
+
+### **5. ReSortFileName(Path: string) 的連續性維護**
+
+為了保證 UI 上顯示的頁碼順序與磁碟檔名一致,此方法採用「先暫存、後改名」的策略:
+
+- **防止衝突**:先將目錄內所有符合格式的影像更名為帶有臨時前綴(如 @)的檔名。
+- **按序更名**:讀取 Context.dat 內的清單,依照目前的順序,將檔案逐一更名為 001_..., 002_... 等格式。
+- **同步索引**:最後將更名後的結果重新寫入 Context.dat。
+
+### **6. GetLocalAppDir(Handle: HWND) 的權限繞過**
+
+這是一個系統級別的 IO 位置定位方法:
+
+- **API 呼叫**:呼叫 SHGetSpecialFolderPath (Windows Shell API)。
+- **定位 CSIDL_LOCAL_APPDATA**:指向 C:\Users\使用者名稱\AppData\Local\。
+- **必要性**:這能解決 OCX 程式被安裝在 Program Files 下時,因為 UAC 權限無法在安裝目錄寫入 Log 或語言檔的問題。
+
+### **🎯 移植至 Web 平台的建議**
+
+當您將這些邏輯移植到 Web 時:
+
+- Str2Dir 應對應到 **IndexedDB** 的 Object Store 建立或 **File System Access API** 的 getDirectoryHandle(搭配 create: true)。
+- FindFirst / FindNext 在 Web 端應對應到 Directory Handle 的 entries() 異步疊代器。
+- .dat 序列化文件在 Web 端建議直接轉為 **JSON** 格式存儲於瀏覽器的 localStorage 或 IndexedDB 中。
+
+## **柒、 設定檔回寫邏輯 (Write-back Logic)**
+
+本節說明專案中哪些 .ini 檔案會由 OCX 主動更新資料及其觸發時機。
+
+| **檔案名稱** | **回寫內容 (Content)** | **觸發時機 (Trigger)** |
+| --- | --- | --- |
+| **Scan.ini** | DPI、Duplex、亮度、對比、影像模式 | 掃描前設定變更或啟動掃描時(SaveScanPara)。 |
+| **CustomDocNo.ini** | 自訂文件名稱與 ID 映射 | 操作員新增自訂分類或呼叫 `DeleteCustomDocDir` 時。 |
+| **CB_IMGPSScan.ini** | 版本號、伺服器 IP/Port | 自動更新完成後更新版號,或手動修改伺服器設定時。 |
+| | | |
+
+## **捌、 注意事項**
+
+- **硬編碼路徑**:ActiveFormCreate 中存在寫死的 C:\Temp\IMGPSScan,適合作為最終保險。
+- **權限問題**:作為 ActiveX,這些 IO 操作強烈依賴瀏覽器的「安全站台設定」或 IE 的「保護模式」。使用 GetLocalAppDir 是現代化重構中解決 UAC 權限問題的重要手段。
diff --git "a/doc/curtis/OCX_\346\272\235\351\200\232\350\210\207_\346\212\275\350\261\241\345\261\244\346\212\275\346\217\233.md" "b/doc/curtis/OCX_\346\272\235\351\200\232\350\210\207_\346\212\275\350\261\241\345\261\244\346\212\275\346\217\233.md"
new file mode 100644
index 0000000..65dba92
--- /dev/null
+++ "b/doc/curtis/OCX_\346\272\235\351\200\232\350\210\207_\346\212\275\350\261\241\345\261\244\346\212\275\346\217\233.md"
@@ -0,0 +1,249 @@
+# **TCB_IMGPSScanX OCX 通訊介面與溝通機制分析**
+
+本表條列了 Delphi 宿主環境(ActiveX[ocx]) 與 TCB_IMGPSScanX 元件之間主要的溝通管道、對應方法及其在系統架構中的作用。
+
+## **壹、 指令與資料交換介面表**
+
+| **通訊方法 (Method)** | **通訊方向** | **溝通內容 (Data Payload)** | **具體作用與目的** |
+| --- | --- | --- | --- |
+| **SetSQLData** | **宿主 -> OCX** | 以 ` | 或,` 分隔的長字串(如:IP, CaseID, DPI) |
+| **GetSQLData** | **宿主 <-> OCX** | 指定 Key (如 'PARA_NO') 取得對應 Value | **資料查詢通道**。宿主可詢問 OCX 目前快取清單中的特定數值,用於介面同步或邏輯判斷。 |
+| **GetSetInf1 ~ 7** | **宿主 <- OCX** | 單一字串值 (如 CaseID, 總張數, 成功標記 'Y') | **狀態出口 (Outlets)**。提供標準化的 7 個出口,讓 JavaScript 或宿主 App 輪詢(Polling)目前的執行結果或掃描統計。 |
+| **StatrTwainScan** | **宿主 -> OCX** | 無參數 (觸發動作) | **硬體啟動指令**。宿主程式按下「開始掃描」按鈕後呼叫此方法,通知 OCX 喚起 TWAIN 驅動程式。 |
+| **GetCurrentVersionNo** | **宿主 <- OCX** | 版本字串 (如 '1.0.3.5') | **版本識別**。宿主程式載入 OCX 後第一步通常會呼叫此處,用以比對伺服器版本並決定是否強制更新。 |
+| **upFile** | **宿主 -> OCX** | 無或部分參數 (觸發網路 IO) | **輸出指令**。通知 OCX 將本機暫存區的檔案(如 ZIP 包)依照先前設定好的路徑與權限上傳至伺服器。 |
+| **dnFile_Get** | **宿主 -> OCX** | 遠端 Action 關鍵字與本地檔名 | **同步指令**。通知 OCX 向伺服器抓取特定資源(如 XML 規則或語言檔)並存放到指定 IO 路徑。 |
+| **ActiveFormCreate** | **系統 -> OCX** | 視窗建立事件 | **環境初始化**。當宿主程式實體化 OCX 時,自動觸發此處執行 GetDefScanIni,確保掃描環境就緒。 |
+| **Property CaseID** | **宿主 <-> OCX** | WideString | **屬性直連**。透過 COM 屬性機制直接設定或讀取案件編號。 |
+| **Property ScreenSnap** | **宿主 -> OCX** | Boolean | **功能切換**。控制 OCX 是否要在特定時機執行螢幕截圖稽核。 |
+
+## **貳、 溝通機制細部說明**
+
+### **1. 參數化配置 (Config-by-String)**
+
+本專案大量使用 SetSQLData 這種「一條字串走天下」的設計,這在早期 ActiveX 開發中非常流行,優點是規避了 COM 介面頻繁修改 _TLB.pas 的麻煩。您在轉換 TypeScript UI 時,可以將其封裝為一個 JSON 物件,最後再組合成字串傳給這個方法。
+
+### **2. 狀態回饋 (The Inf1~7 Pattern)**
+
+由於 ActiveX 事件 (Events) 的回傳有時在網頁端不夠穩定,開發者選擇了 GetSetInf 系列。宿主程式通常會在執行完某個長耗時動作(如 upFile)後,連續呼叫 GetSetInf3 (成功標記) 與 GetSetInf6 (錯誤訊息) 來決定下一步 UI 流程。
+
+### **3. 雙向同步 (Bidirectional Sync)**
+
+- **同步設定**:宿主透過 GetDefScanIni 觸發,OCX 內部完成硬體設定。
+- **同步資料**:宿主透過 dnFile_Get 觸發,OCX 完成本機與伺服器的檔案 IO 同步。
+
+# **參、描服務抽象層實作**
+
+採用 **「抽象介面層 (Abstraction Layer)」** 配合 **「適配器模式 (Adapter Pattern)」**,處理遺留系統(Legacy System)過渡到現代化架構
+
+```tsx
+/**
+ * 掃描服務資料模型定義
+ * 將原本 OCX 雜亂的字串溝通 (SetSQLData) 結構化
+ */
+export interface ScanConfig {
+ serverIp: string;
+ caseId: string;
+ dpi: number;
+ isColor: boolean;
+ isDuplex: boolean;
+ // ... 其他來自 GetDefScanIni 的參數
+}
+
+export interface ScanStatus {
+ caseId: string;
+ totalPageCount: number;
+ isUploadSuccess: boolean;
+ lastBarcode: string;
+ errorMessage: string;
+}
+
+/**
+ * 掃描服務抽象介面 (IScanService)
+ * UI 層僅與此介面溝通,不直接操作底層實作
+ */
+export interface IScanService {
+ initialize(config: ScanConfig): Promise<void>;
+ startScan(): Promise<boolean>;
+ uploadFiles(): Promise<boolean>;
+ getStatus(): Promise<ScanStatus>;
+ getVersion(): Promise<string>;
+ downloadResource(action: string, fileName: string): Promise<void>;
+}
+
+/**
+ * 實作 A: ActiveX 適配器 (Legacy Adapter)
+ * 用於目前環境:UI (TS) -> Delphi Browser -> ActiveX (OCX)
+ */
+export class ActiveXScanAdapter implements IScanService {
+ private ocx: any;
+
+ constructor() {
+ // 透過 window.external 或 Delphi Bridge 取得 OCX 實例
+ this.ocx = (window as any).OCX_INSTANCE;
+ }
+
+ async initialize(config: ScanConfig): Promise<void> {
+ // 將 JSON 轉回 OCX 慣用的管道分隔字串 (SetSQLData 邏輯)
+ const sqlDataStr = `${config.serverIp}|${config.caseId}|${config.dpi}|${config.isColor ? 'C' : 'G'}`;
+ this.ocx.SetSQLData(sqlDataStr);
+ }
+
+ async startScan(): Promise<boolean> {
+ this.ocx.StatrTwainScan();
+ return true; // 實際狀態需透過 GetSetInf 輪詢
+ }
+
+ async getStatus(): Promise<ScanStatus> {
+ return {
+ caseId: this.ocx.GetSetInf1(),
+ totalPageCount: parseInt(this.ocx.GetSetInf2()),
+ isUploadSuccess: this.ocx.GetSetInf3() === 'Y',
+ lastBarcode: this.ocx.GetSetInf5(),
+ errorMessage: this.ocx.GetSetInf6()
+ };
+ }
+
+ async uploadFiles(): Promise<boolean> {
+ this.ocx.upFile();
+ return true;
+ }
+
+ async getVersion(): Promise<string> {
+ return this.ocx.GetCurrentVersionNo();
+ }
+
+ async downloadResource(action: string, fileName: string): Promise<void> {
+ this.ocx.dnFile_Get(action, fileName);
+ }
+}
+
+/**
+ * 實作 B: Backend Server 適配器 (Future Adapter)
+ * 用於未來環境:UI (TS) -> REST API / WebSocket -> Rust/Go Backend
+ */
+export class BackendServerAdapter implements IScanService {
+ private apiUrl = "http://localhost:8080/api/scanner";
+
+ async initialize(config: ScanConfig): Promise<void> {
+ await fetch(`${this.apiUrl}/config`, {
+ method: 'POST',
+ body: JSON.stringify(config)
+ });
+ }
+
+ async startScan(): Promise<boolean> {
+ const res = await fetch(`${this.apiUrl}/scan`, { method: 'POST' });
+ return res.ok;
+ }
+
+ async getStatus(): Promise<ScanStatus> {
+ const res = await fetch(`${this.apiUrl}/status`);
+ return await res.json();
+ }
+
+ async uploadFiles(): Promise<boolean> {
+ const res = await fetch(`${this.apiUrl}/upload`, { method: 'POST' });
+ return res.ok;
+ }
+
+ async getVersion(): Promise<string> {
+ const res = await fetch(`${this.apiUrl}/version`);
+ const data = await res.json();
+ return data.version;
+ }
+
+ async downloadResource(action: string, fileName: string): Promise<void> {
+ // 未來可能直接由後端處理,前端僅發送同步指令
+ await fetch(`${this.apiUrl}/sync?action=${action}&file=${fileName}`);
+ }
+}
+
+/**
+ * 服務工廠 (Scanner Factory)
+ * 根據環境自動切換實作
+ */
+export class ScannerFactory {
+ static getService(): IScanService {
+ if ((window as any).OCX_INSTANCE) {
+ console.log("偵測到 ActiveX 環境,啟用 ActiveX 適配器");
+ return new ActiveXScanAdapter();
+ } else {
+ console.log("現代瀏覽器環境,啟用後端 API 適配器");
+ return new BackendServerAdapter();
+ }
+ }
+}
+```
+
+### **1. 介面標準化(JSON 化)**
+
+原先 OCX 使用 SetSQLData 的「長字串」溝通是非常脆弱的(一項參數順序錯了就全毀)。在 TypeScript 抽象層中,請務必將其轉換為 **強型別的 JSON 物件**(如 ScanConfig 介面)。這樣你的 UI 邏輯在處理設定時會非常直覺。
+
+### **2. 非同步處理(Promise/Async)**
+
+ActiveX 的方法通常是同步阻塞的,而後端 API 是非同步的。
+
+- **建議**:在抽象介面(IScanService)中,所有方法都回傳 Promise。
+- **原因**:這樣當你未來切換到後端伺服器(fetch API)時,UI 的調用邏輯(await service.startScan())不需要做任何修改。
+
+### **3. 實作「心跳」或「狀態輪詢」**
+
+原本 GetSetInf1~7 主要是靠宿主程式主動去「問」OCX。
+
+- **抽象層建議**:在 IScanService 中實作一個 subscribeStatus(callback) 的觀察者模式。
+- **ActiveX 模式下**:在適配器內部啟動一個 setInterval 去輪詢 GetSetInf。
+- **未來後端模式下**:適配器改用 **WebSocket** 接收後端主動推播的掃描事件。
+- **UI 層感受**:UI 只需要處理 onStatusUpdate 事件,根本不用管底層是用輪詢還是 WebSocket。
+
+### **4. 資源路徑的轉義(The Bridge Proxy)**
+
+這是我之前提到的關鍵:由於 iframe 裡的 TypeScript 無法存取 C:\Temp,但 ActiveX 依舊會把檔案掃到那裡。
+
+- **策略**:你的 Delphi Browser 需要實作一個簡單的本地 Proxy。
+- **實作**:當 TypeScript 需要顯示圖檔時,它請求 http://local.bridge/view/001.tif,Delphi Browser 攔截此請求並從實體路徑讀取檔案回傳。
+- **好處**:未來改為 Backend Server 時,Server 也可以提供同樣的 URL 格式,UI 完全無縫接軌。
+
+## **肆、 Delphi 與 JavaScript 通訊橋樑 (Bridge) 實作說明**
+
+當您在 Delphi 宿主程式中使用內嵌瀏覽器時,JavaScript 取得 `OCX_INSTANCE` 的方式取決於底層的瀏覽器引擎:
+
+### **1. 舊版 IE 核心 (TWebBrowser / window.external)**
+
+這是最傳統的方式,Delphi 會透過實作 `IDocHostUIHandler` 介面,將一個自訂的 `IDispatch` 物件掛載到 `window.external` 上。
+
+- **Delphi 端**:將 `TCB_IMGPSScanX` 實例或其包裝類別指派給瀏覽器的 `External` 屬性。
+- **JS 端**:直接使用 `window.external.StatrTwainScan()` 呼叫。
+
+### **2. 新版 Edge 核心 (TEdgeBrowser / WebView2 Host Objects)**
+
+這是現代化的做法。Delphi 透過 WebView2 的 API 將物件直接「注入」到 JS 的命名空間中。
+
+- **Delphi 端執行**:
+
+ ```pascal
+ // 將 OCX 物件以 'OCX_INSTANCE' 名稱注入
+ EdgeBrowser.AddHostObjectToScript('OCX_INSTANCE', MyOcxWrapperObject);
+ ```
+
+- **JS 端取得**: WebView2 會將物件放置在 `window.chrome.webview.hostObjects` 底下。
+
+ ```jsx
+ const ocx = window.chrome.webview.hostObjects.OCX_INSTANCE;
+ ```
+
+
+### **3. 為什麼需要 Wrapper (包裝類別)?**
+
+通常我們**不建議**直接將 `TCB_IMGPSScanX` 注入,原因如下:
+
+1. **安全性**:直接暴露 COM 元件可能會有安全漏洞。
+2. **相容性**:OCX 的某些方法回傳型別(如 Delphi 的自訂 Enum)JavaScript 無法識別。
+3. **執行緒優化**:Delphi 可以在 Wrapper 中使用 `TThread.Queue` 確保掃描指令在正確的執行緒執行,避免瀏覽器 UI 凍結。
+
+### **4. 溝通路徑總結**
+
+1. **Delphi 宿主程式** 啟動並實體化 **OCX 控制項**。
+2. **Delphi 宿主程式** 建立 **Browser 物件** 並載入 **TypeScript UI (HTML)**。
+3. **Delphi 宿主程式** 呼叫瀏覽器 API(如 `AddHostObjectToScript`),將 OCX 的操作介面「注入」到該網頁的 `window` 物件中。
+4. **TypeScript** 透過抽象層 (Adapter) 取得該物件,實現「網頁點按鈕,掃描機開動」的效果。
diff --git "a/doc/curtis/ScanImp_\346\272\220\347\242\274\345\210\206\346\236\220.md" "b/doc/curtis/ScanImp_\346\272\220\347\242\274\345\210\206\346\236\220.md"
new file mode 100644
index 0000000..8781c3c
--- /dev/null
+++ "b/doc/curtis/ScanImp_\346\272\220\347\242\274\345\210\206\346\236\220.md"
@@ -0,0 +1,242 @@
+# **核心源碼與物件實作解析**
+
+本文件針對 CB_IMGPSScanImp.pas 中的核心方法與隱藏物件進行原始碼級別的邏輯拆解與推導。
+
+## **壹、 核心方法源碼說明**
+
+### **1) TCB_IMGPSScanX.GetCurrentVersionNo**
+
+- **功能描述**:取得目前 OCX 元件的版本號。這通常提供給網頁端的 JavaScript 呼叫,用來判斷客戶端的 OCX 是否需要觸發更新下載。
+- **實作推導與底層 API 說明**:
+
+ 在 Delphi 中,若要動態讀取編譯進 OCX 的 VS_VERSION_INFO 資源,標準作法是呼叫一系列的 Windows API。這段實作通常包含以下三個關鍵概念:
+
+1. **HInstance (實體句柄)**:
+- 這是 Delphi 提供的一個全域變數,代表目前載入記憶體中的模組(即這個 OCX 檔)的「實體句柄 (Instance Handle)」。
+- 在 Windows 作業系統中,當一個執行檔 (EXE) 或動態連結檔 (DLL/OCX) 被載入記憶體時,會獲得一個記憶體基底位址,HInstance 就是指向這個位址的指標。Windows 需要這個值來識別「你要操作的是哪一個載入的模組」。
+1. **GetModuleFileName 的作用**:
+- 這是一個 Windows API。它的作用是利用前面提到的 HInstance,向作業系統反查出這個模組在硬碟上的**「完整實體檔案路徑」**(例如:C:\Windows\Downloaded Program Files\CB_IMGPSScan.ocx)。
+- 因為我們需要讀取檔案本身的版本資訊,程式必須先知道「我自己到底存放在硬碟的哪裡」。
+1. **後半段 VerQueryValue 的運作邏輯**:
+
+ 取得檔案路徑後,讀取版本資訊會經過三部曲,而 VerQueryValue 是最後負責「解析」的關鍵:
+
+- **Step 1 (GetFileVersionInfoSize)**:先問 Windows 這個檔案的版本資訊區塊有多大。
+- **Step 2 (GetFileVersionInfo)**:把整塊版本資訊的二進位原始資料 (Raw Data) 完整讀進一段記憶體緩衝區中。
+- **Step 3 (VerQueryValue)**:因為剛剛讀進來的是一包無法直接閱讀的二進位資料,VerQueryValue 的作用就是**「在這包資料中進行精準查詢」**。透過傳入特定的查詢路徑(例如傳入 \ 可以取得包含主版號、次版號的 VS_FIXEDFILEINFO 結構體;或是傳入特定語系代碼如 \StringFileInfo\040404E4\FileVersion),作業系統會幫你把二進位資料解析成我們需要的字串或數字版本號(如 1.0.3.5)。
+
+### **2) TCB_IMGPSScanX.ActiveFormCreate**
+
+- **功能描述**:這是 ActiveX 視覺化窗體 (Form) 的生命週期起點。當 IE 瀏覽器或應用程式載入這個 OCX 時,首先觸發的初始化事件。
+- **實作推導**:
+
+ 它會負責初始化全域變數、設定第三方元件的預設值、並建立暫存資料夾。
+
+ ```pascal
+ procedure TCB_IMGPSScanX.ActiveFormCreate(Sender: TObject);
+ begin
+ // 1. 預設變數初始化
+ Def_DeviceDelete := True;
+ Def_ScannerReverse := False;
+
+ // 2. 建立本機暫存目錄
+ ForceDirectories('C:\Temp\IMGPSScan');
+
+ // 3. UI 語系初始化
+ InitialLanguage;
+ end;
+ ```
+
+
+### **3) TCB_IMGPSScanX.StatrTwainScan**
+
+- **功能描述**:啟動掃描機的 TWAIN 介面,開始進紙或掃描。(註:Statr 應為 Start 的早期拼字錯誤,這在舊專案中很常見)。
+- **實作推導**:
+
+ 這個方法會讀取網頁傳進來的參數(如 DPI、色彩),設定給 Scanner 物件,然後發出擷取指令。
+
+ ```pascal
+ procedure TCB_IMGPSScanX.StatrTwainScan;
+ begin
+ // 設定解析度與顏色
+ Scanner.Resolution := StrToIntDef(Fimgdpi, 200);
+ if Fscancolor = 'C' then
+ Scanner.PixelType := ptColor
+ else
+ Scanner.PixelType := ptGray;
+
+ // 啟動掃描 (會喚起實體掃描機)
+ Scanner.Acquire;
+ end;
+ ```
+
+
+### **4) TCB_IMGPSScanX.OnAcquire 與資料流物件**
+
+- **功能描述**:這是 Scanner (EnScan) 最核心的事件。當掃描機成功掃完「一張」影像並傳入電腦記憶體時,會觸發此事件。
+- **源碼邏輯推導**:
+
+ ```pascal
+ procedure TCB_IMGPSScanX.ScannerAcquire(Sender: TObject; DibHandle: THandle; var Handled: Boolean);
+ var
+ MyStream: TMemoryStream;
+ MyGraphic: TDibGraphic;
+ begin
+ // 1. 將 DibHandle 轉換為 Delphi 影像物件
+ MyGraphic := TDibGraphic.Create;
+ MyGraphic.Handle := DibHandle;
+
+ // 2. 影像處理 (如去斜、黑白轉換)
+
+ // 3. 存入記憶體串流或實體檔案
+ // ...
+ end;
+ ```
+
+- **三大核心資料物件解釋**:
+1. **DibHandle**:這是 Windows 底層的「全域記憶體句柄 (Global Memory Handle)」。掃描機驅動把圖片放在記憶體裡,給你這個代號。你必須透過 TDibGraphic 來「解讀」這塊記憶體。
+2. **TMemoryStream**:**記憶體串流**。它的作用像是一塊存在 RAM 裡的虛擬硬碟。掃描後的圖檔在還沒存到實體硬碟前,會先放在這裡進行格式轉換 (如轉成 JPEG) 或進行 MD5 計算,因為在記憶體中操作速度最快。
+ - **DeleteStm : TMemoryStream 的逐行操作說明**:
+ 在 `OnAcquire` 事件中,`DeleteStm` 主要用於「空白頁判定」。其源碼邏輯如下:
+
+ ```pascal
+ // 判定是否啟動空白頁刪除功能
+ if Def_DeviceDelete then
+ begin
+ // 1. 在 Heap 記憶體中建立一個暫存串流物件
+ DeleteStm := TMemoryStream.Create;
+ try
+ // 2. 將當前掃描到的影像物件 (MyGraphic) 寫入記憶體串流
+ // 這會根據 TIFF G4 等格式進行壓縮,產生實際的檔案位元組資料
+ MyGraphic.SaveToStream(DeleteStm);
+
+ // 3. 核心判定:檢查該影像在記憶體中所佔用的位元組大小 (Size)
+ // 若小於預設門檻值 (Def_DeviceDeleteSize, 如 3072 Bytes)
+ if DeleteStm.Size < Def_DeviceDeleteSize then
+ begin
+ // 4. 若符合空白頁特徵,則不進行存檔動作,直接跳出此 Procedure
+ // 並告知掃描控制項此頁已處理完畢 (Handled := True)
+ Handled := True;
+ Exit;
+ end;
+ finally
+ // 5. 無論是否為空白頁,操作結束後必須釋放記憶體,避免 Memory Leak
+ DeleteStm.Free;
+ end;
+ end;
+ ```
+
+ -
+3. **TFileStream**:**檔案串流**。用來直接對硬碟讀寫資料。當確認影像無誤後,會透過 TFileStream 將 TMemoryStream 的內容真實地寫入 C:\Temp\...\001.tif 中。
+
+### **5) TCB_IMGPSScanX.FindISB2View**
+
+- **功能描述**:用來在畫面上尋找並更新用來預覽圖片的元件。
+- **名詞解釋**:**ISB 代表 ImageScrollBox**。
+
+ 這對應到 uses 區段中的 EnImgScr 套件。TImageScrollBox 是 Envision 提供的一個 UI 元件,專門用來顯示超出螢幕大小的掃描圖檔,支援平滑拖曳與縮放。這個方法通常用來把剛掃描完的 DibHandle 餵給畫面上的 ISB 元件顯示。
+
+
+### **6) TCB_IMGPSScanX.GetNoNameCase**
+
+- **功能描述**:處理「無案號」或「未知歸屬」的掃描件。
+- **源碼實作逐行說明**:
+
+ 此方法透過迴圈尋找一個尚未被使用的目錄名稱(格式為「未配號 + 四位數字」)。
+
+
+```pascal
+Function TCB_IMGPSScanX.GetNoNameCase(Path:String):String; // 取未配號XXXX
+var
+ i : Integer; // 宣告迴圈計數器
+begin
+ // 1. 啟動一個從 1 到 9999 的迴圈,尋找可用的索引值
+ for i := 1 to 9999 do
+ begin
+ // 2. 檢查特定路徑下的目錄是否已存在
+ // _Msg('未配號'):取得「未配號」字串(可能具備多國語言處理)
+ // Add_Zoo(i, 4):將數字 i 補齊為 4 位數(例如 1 變為 0001)
+ if Not DirectoryExists(Path + _Msg('未配號') + Add_Zoo(i, 4)) then
+ begin
+ // 3. 若該目錄不存在,代表此名稱可用,設定 Result 並跳出迴圈
+ Result := _Msg('未配號') + Add_Zoo(i, 4);
+ Break; // 找到第一個可用的名稱後立即停止搜尋
+ end;
+ end;
+end;
+```
+
+### **7) TCB_IMGPSScanX.SetSQLData 與 8) GetSQLData**
+
+這兩個方法是 OCX 與網頁 (JS) 溝通的雙向橋樑。
+
+- **SetSQLData (網頁 -> OCX)**:接收由網頁傳來的設定字串(通常用 | 或 , 分隔,例如 192.168.1.1|L12345678|200|C),在內部將字串切開 (Split),並分別賦值給 ServerIP, FCaseID, Fimgdpi, Fscancolor 等內部變數。
+- **GetSQLData (OCX -> 網頁)**:將 OCX 內部的處理結果(例如:UploadSuccess|3|0 代表上傳成功、共 3 頁、0 錯誤),組合成一個長字串後回傳給網頁端的 JS 進行後續的頁面跳轉或提示。
+
+### **8) TCB_IMGPSScanX.GetDefScanIni**
+
+- **功能描述**:取得並套用掃瞄參數的預設值與自訂設定。
+- **源碼實作解析**:
+ - **硬編碼預設值 (Hardcoded Defaults)**:
+
+ 程式一開始會先寫死一組標準值,例如 Def_ScanDpi := 300 (預設 300 DPI)、Def_DeviceDeleteSize := 3072 (空白頁判定門檻為 3KB)。
+
+ - **動態配置覆蓋 (Dynamic Overriding)**:
+
+ 透過 for i := 0 to WORK_INF_List.Count - 1 do 迴圈遍歷設定檔清單。使用 GetSQLData 取得參數代號 (PARA_NO) 與內容 (PARA_CONTENT)。
+
+- **屬性設定對照表**:
+
+ 下表整理了此方法中設定的所有關鍵屬性、其對應的參數代號及功能說明。
+
+ | **屬性名稱 (內部變數)** | **對應 PARA_NO** | **PARA_CONTENT 處理方式(GetSQLData)** | **功能說明** |
+ | --- | --- | --- | --- |
+ | **Def_DeviceDelete** | SCAN_BLANKDEL_USE | 'Y' -> True, Else -> False | 空白頁自動刪除開關。 |
+ | **Def_DeviceDeleteSize** | SCAN_BLANKDEL_SIZE | StrToInt (若空則 0) | 空白頁判定門檻 (Bytes)。 |
+ | **Def_ScannerReverse** | SCAN_REVERSE | 'Y' -> True, Else -> False | 影像是否反相。 |
+ | **Def_BoardClear** | SCAN_BOARDCLEAR | 'Y' -> True, Else -> False | 是否清除影像黑邊。 |
+ | **Def_ScanDpi** | SCAN_DPI | StrToInt (若空則 300) | 掃描解析度。 |
+ | **Def_ScanDuplex** | SCAN_DUPLEX | 'Y' -> True, Else -> False | 是否啟用雙面掃描。 |
+ | **Def_ScanRotate** | SCAN_ROTATE_MODE | '0'->0, '1'->270, '2'->180, '3'->90 | 掃描旋轉角度映射。 |
+ | **Def_ScanDeskew** | SCAN_DESKEW | 'Y' -> True, Else -> False | 是否自動矯正傾斜。 |
+ | **Def_ScanImgSetUse** | SCAN_IMGSET_USE | 'Y' -> True, Else -> False | 是否使用亮度/對比設定。 |
+ | **Def_ScanBright** | SCAN_BRIGHT | StrToInt (限制 -255~255) | 亮度數值。 |
+ | **Def_ScanContrast** | SCAN_CONTRAST | StrToInt (限制 -255~255) | 對比數值。 |
+ | **Def_ScanImgShowMode** | SCAN_SHOW_MODE | '0','1','2' 對應模式 | 影像顯示/縮放模式。 |
+ | **ScanDenialTime** | CASE_IN_TIME | 直接存為 String | 進件截止時間限制。 |
+ | **ScanDenialHint** | SCAN_HINT | 直接存為 String | 掃描畫面提示字串。 |
+ | **NoSaveBarCodeList** | NO_SAVE_FORM_ID | CommaText := Value | 不存檔之表單代號清單。 |
+ | **ImagePath** | LOCAL_PATH | 直接存為 String | 本機端暫存路徑。 |
+ | **GuideFormIDList** | GUIDEFORMID | CommaText := Value | 導引頁表單 ID 清單。 |
+ | **DivPageFormIDList** | DIVPAGEFORMID | CommaText := Value | 分案頁表單 ID 清單。 |
+ | **FJpgCompression** | FILE_COMPRESSION | StrToInt | JPG 轉 TIF 壓縮比。 |
+ | **FMaxUploadSize** | MAX_UPLOAD_SIZE | 直接存為 String | 上傳大小限制 (MB)。 |
+
+## **貳、 記憶體直接操作實作清單**
+
+以下條列專案中直接涉及記憶體操作的程式區段:
+
+### **記憶體操作對應位置表**
+
+| **記憶體操作對象** | **所屬 Function / Procedure** | **關鍵操作關鍵字 / 代碼** | **記憶體特性說明** | 註記 |
+| --- | --- | --- | --- | --- |
+| **HInstance** | GetCurrentVersionNo | GetModuleFileName(HInstance, ...) | 模組載入位址。 | 增API版本號 |
+| **資源緩衝區** | GetCurrentVersionNo | VerQueryValue, GetFileVersionInfo | 透過 Pointer 進行二進位搜尋。 | 增API版本號 |
+| **DibHandle** | onAcquire | MyGraphic.Handle := DibHandle; | Windows 全域記憶體句柄轉移。 | 改套件實作/Rust |
+| **TMemoryStream** | onAcquire | MemoryStream.Write, .Read | Heap Memory 內部二進位操作。 | |
+
+## **參、 遺失物件反推與說明**
+
+你提到在原始碼中找不到 _DelTree 和 Scanner 的實作,這是因為它們屬於以下兩種情況:
+
+### **1) TCB_IMGPSScanX._DelTree**
+
+- **這是一個自訂的私有輔助函式 (Private Helper)**。
+- **功能**:它的名稱源自 DOS 時代的指令 deltree(刪除整個目錄樹)。在 ActiveX 中,當上傳伺服器成功後,必須清空 C:\Temp\案件編號\ 裡的所有暫存圖檔與資料夾以釋放空間,並防止資料外洩。
+- **實作原理**:由於早期的 Delphi 沒有內建遞迴刪除目錄的單一指令,開發者通常會自己寫一個 _DelTree,裡面使用 FindFirst, FindNext 找出所有檔案並用 DeleteFile 刪除,最後用 RemoveDir 砍掉資料夾。
+
+### **2) Scanner**
+
+- **這是一個視覺化/非視覺化的第三方元件實例 (Component Instance)**。
+- **為何找不到宣告?** 因為在 Delphi 中,如果你是透過 IDE 的工具箱 (Tool Palette) 將 TEnScan 元件直接拖拉到窗體 (Form) 上,IDE 會自動把它寫在 .dfm 檔裡,並在 TCB_IMGPSScanX 類別的 published 區段自動產生一行 Scanner: TEnScan;。
+- **功能**:它就是 **Envision SDK** 裡用來與 TWAIN 硬體溝通的靈魂核心。所有的掃描屬性 (Scanner.Resolution) 與方法 (Scanner.Acquire) 都是對這個物件進行操作。
diff --git a/doc/curtis/Scanner_Controller_Analysis.md b/doc/curtis/Scanner_Controller_Analysis.md
new file mode 100644
index 0000000..964c8d8
--- /dev/null
+++ b/doc/curtis/Scanner_Controller_Analysis.md
@@ -0,0 +1,62 @@
+# 硬體掃描控制模組 (Scanner Controller) 深度分析
+
+在 `CB_IMGPSScanImp.pas` 中,「硬體掃描控制模組」是系統與實體掃描設備溝通的唯一橋樑。它深度依賴 TWAIN 協定(透過第三方元件 `EnScan` 封裝),負責控制硬體行為並將紙本文件轉換為記憶體中的數位影像資料。
+
+若要將此模組進一步細拆,其內部組成可分為以下三大子分類:
+
+---
+
+## 1. TWAIN 介面封裝與控制 (TWAIN Interface Wrapper)
+
+**職責**:負責管理實體掃描機的連線狀態、開啟/關閉資料來源 (Data Source),以及觸發掃描動作。
+**核心實作特性**:
+* **掃描機選擇與初始化**:
+ * `SelectScanner` (`scanner.SelectScanner`):呼叫 TWAIN 介面讓使用者選擇預設的掃描機硬體。
+ * `initkscan` / `CheckScannerConfig`:在系統啟動時檢查掃描機是否已正確配置並支援特定功能(例如檢查 `Scanner.DuplexCap > 0` 確認是否支援雙面掃描)。
+* **掃描生命週期管理** (`StatrTwainScan`):
+ * 負責設定 `Scanner.OpenSource`(開啟驅動)。
+ * 呼叫 `Scanner.AcquireWithSourceOpen` 開始非同步擷取,並傳入回呼函式 (Callback) 的指標與自訂的狀態結構 (`LongInt(@ScanInfo)`)。
+ * 確保無論掃描成功、失敗或中斷,最終都會安全地執行 `Scanner.CloseSource`。
+
+## 2. 掃描參數與設定管理器 (Scanner Profile Manager)
+
+**職責**:負責載入、維護及套用掃描時所需的各項硬體與前處理參數。這些參數通常從資料庫 (`WORK_INF`) 或是本機的 `FBScan.ini` 中讀取。
+**核心實作特性**:
+* **硬體基本參數 (Hardware Params)**:
+ * `ScanDpi`:解析度設定,對應 `RequestedXDpi` 與 `RequestedYDpi`。
+ * `ScanColor` (`TImageFormat`):影像色彩模式(黑白 `ifBlackWhite`、灰階 `ifGray256`、彩色 `ifTrueColor`)。
+ * `ScanDuplex`:控制硬體是否開啟雙面進紙 (`Scanner.Duplex`)。
+ * `TwainShowUI`:是否顯示掃描機原廠的 TWAIN 設定畫面 (`Scanner.ShowUI`)。
+* **硬體增強參數 (Enhancement Params)**:
+ * `ScanBright` (亮度) 與 `ScanContrast` (對比度):當啟用 `ScanImgSetUse` 時,將這些參數直接送入掃描硬體。
+* **前置處理規則 (Pre-processing Rules)**:
+ * `DeviceDelete` 與 `DeviceDeleteSize`:定義是否開啟「空白頁自動刪除」以及刪除的位元組閥值。
+ * `ScannerReverse` (反相)、`ScanDeskew` (硬體/初階去斜)、`BoardClear` (清除黑邊)。
+
+## 3. 非同步影像接收與初始轉換器 (Acquisition Event Handler)
+
+**職責**:做為掃描機與應用程式記憶體的交界點,負責攔截驅動程式傳回的原始記憶體區塊 (`DibHandle`),並進行最基礎的安全轉換與前置判斷。
+**核心實作特性** (`OnAcquire` 回呼事件):
+* **記憶體接管 (Memory Handover)**:
+ * 接收來自 TWAIN 驅動的 `DibHandle`(Device Independent Bitmap 記憶體指標)。
+ * 利用 `pScanInfo^.Graphic.AssignFromDibHandle(DibHandle)` 將非管理的記憶體轉換為 Delphi VCL 的 `TTiffGraphic` 物件。
+* **早階條碼快篩與方向校正 (Early Barcode Detection & Rotation)**:
+ * 為確保後續處理正確,系統會在剛拿到記憶體影像時,立刻進行一次快速的條碼掃描 (`MpsGetBarcode`)。
+ * 讀取條碼所帶的方向資訊 (`MpsBarcodeinf.r180`),並在記憶體中立刻進行 `Rotate` 旋轉,將顛倒或橫放的文件轉正。
+* **基礎裁切與壓縮決策 (Format & Crop Decision)**:
+ * **A3 裁 A4**:呼叫 `CheckNeedCrop` 判斷長寬比例與特定條碼數量,若確認為 A3 合併頁,則立刻在記憶體中將其拆分為 `iGraphic_First` 與 `iGraphic_Sec` 兩張獨立影像。
+ * **格式與壓縮決策**:針對色彩屬性 (`ifBlackWhite`, `ifTrueColor`, `ifGray256`),決定應該套用哪種壓縮演算法(如黑白套用 `tcGroup4` 或 `tcPackBits`,彩色則轉換為 `tcJpeg` 並套用指定的 `FJpgCompression` 壓縮率)。
+
+---
+
+## 💡 未來重構與微服務化建議
+
+若要將此「硬體掃描控制模組」進行現代化升級或跨平台轉型,建議考量以下方向:
+
+1. **與 UI 徹底解耦**:
+ 目前的 `OnAcquire` 回呼函式中混雜了大量 UI 操作(如 `ImageScrollBox1.Graphic.Assign(...)`)。應改用「發佈-訂閱模式 (Pub-Sub)」,讓 Scanner Controller 收到影像後只觸發事件,由外部的 UI 層去訂閱並更新畫面。
+2. **Web/雲端化架構 (Web TWAIN / WebSockets)**:
+ 若未來系統要走向純 Web 化(捨棄 ActiveX),由於瀏覽器無法直接呼叫 Windows 底層的 TWAIN API,此模組必須被改寫為一隻安裝於 Client 端的 **背景常駐服務 (Local Windows Service / Daemon)**。
+ 該服務可以透過 **WebSocket** 或 **Local REST API** 接收來自網頁端的掃描指令,控制 TWAIN 掃描機,並將接收到的影像轉為 Base64 或二進位流回傳給網頁前端。
+3. **單一職責分離 (Separation of Concerns)**:
+ 應將 `OnAcquire` 中厚重的「條碼辨識」、「A3 裁切」與「黑邊處理」移出此模組。Scanner Controller 的唯一職責應該只有:**「將紙本轉為電腦中的 Bitmap」**。後續的處理應交給 `Image Processor` (影像處理模組) 透過管線 (Pipeline) 的方式接手處理。
diff --git a/doc/curtis/Transport_Manager_Analysis.md b/doc/curtis/Transport_Manager_Analysis.md
new file mode 100644
index 0000000..330fca5
--- /dev/null
+++ b/doc/curtis/Transport_Manager_Analysis.md
@@ -0,0 +1,69 @@
+# 安全傳輸與 API 通訊模組 (Transport Manager) 深度分析
+
+在 `CB_IMGPSScanImp.pas` 中,「安全傳輸與 API 通訊模組」負責處理 ActiveX 客戶端與後端伺服器 (如 Java Servlet 平台) 之間的所有資料交換與檔案傳輸。由於涉及機敏的金融/保險文件,此模組高度依賴加密與安全通訊協定。
+
+若要將此模組進一步細拆,其內部組成可分為以下四大子分類:
+
+---
+
+## 1. HTTP/HTTPS API 請求管理器 (RESTful / Servlet Client Wrapper)
+
+**職責**:專責透過 HTTP(S) 協定,向後端的 Java Servlet 端點發送 GET/POST 請求,用於同步時間、下載設定檔或回報案件狀態。
+**核心實作特性**:
+* **套件依賴**:底層依賴 SecureBlackbox 的 `TElHTTPSClient` (在變數宣告為 `HTTPSClient`) 處理 SSL/TLS 連線。
+* **字串/表單資料交換**:
+ * `ProcessServlet_Get`:使用 HTTP GET 方式,將加密過的參數 (`SendData`) 送至伺服器,並將伺服器回傳的結果寫入 `FReWrite` 或 `Memo1` 中。
+ * `ProcessServlet` / `ProcessServlet_FormData`:使用 HTTP POST 或 `multipart/form-data` 方式提交較大的資料集(如 OMR 檢核結果、案件完成通知等)。
+* **狀態與錯誤攔截**:檢查伺服器回傳的代碼(例如回傳 `0` 代表成功,`1` 代表錯誤,或攔截回傳 HTML 中包含 `login.js` 來判斷 Session 是否逾時登出)。
+
+## 2. 雙協定檔案上傳/下載引擎 (Dual-Protocol File Transfer Engine)
+
+**職責**:處理實體影像檔案(通常是打包後的 ZIP 檔)或系統授權檔的實體傳輸,並根據系統設定動態切換 HTTP 或 FTP 協定。
+**核心實作特性**:
+* **HTTP 檔案傳輸**:
+ * `upFile`:透過 HTTP POST (`multipart/form-data`) 將本地端的檔案 (如 `Img.zip` 或 `.lic` 檔) 上傳至伺服器指定的 Servlet 接收端。
+ * `dnFile_Get` / `dnFile`:透過 HTTP 協定從伺服器下載檔案 (如 `OMRSet.zip`, `KeyinSet.zip` 或舊案影像),並提供下載狀態監控。
+* **FTPS 檔案傳輸 (高頻寬/大檔專用)**:
+ * `GetftpInfo`:先透過 HTTP 向伺服器查詢該案件是否應使用 FTP 傳輸,並取回加密的 FTP 登入資訊。
+ * 依賴 SecureBlackbox 的 `TElSimpleFTPSClient` 建立 FTP over SSL 連線。
+ * `SetFtpInfo`、`IIS_Ftp.FtpsConnect`、`IIS_Ftp.FtpsToMain`、`IIS_Ftp.FtpsDownloadFile`:負責實際的 FTP 登入、切換目錄、上傳與下載操作,完成後呼叫 `FtpCaseComplete` 透過 HTTP 通知伺服器傳檔結束。
+
+## 3. 安全加密與雜湊模組 (Security, Crypto & Hashing Utils)
+
+**職責**:負責資料傳輸前後的加解密運算,以及檔案完整性的 MD5 校驗,確保通訊過程不被竄改。
+**核心實作特性**:
+* **字串加解密 (String Encryption)**:
+ * 利用 `En_DecryptionStr_Base64` 函式(可能來自自訂或第三方的 `Encryp` 單元),對 URL 參數 (如 `checktime`, `col` 欄位清單) 進行加解密,避免敏感資訊在 URL 明文中裸奔。
+ * 解析加密過的 FTP 登入資訊字串。
+* **檔案 MD5 雜湊校驗 (File Hashing)**:
+ * 使用 Indy 的 `TIdHashMessageDigest5` 元件。
+ * `LoadFileGetMD5`:讀取本機影像檔並計算其 MD5 值,用於比對「異動件 (ESCAN)」模式下,檔案是否與伺服器原有的版本一致,防止誤刪或重複傳輸。
+* **憑證管理 (Certificate Management)**:
+ * `HTTPSClientCertificateValidate`:處理 X.509 憑證驗證事件,通常設定為 `Validate := True` 以略過嚴格的自簽憑證檢查(在內部封閉網路中常見的做法)。
+
+## 4. 傳輸前置準備與封裝器 (Payload Archiver & Preparer)
+
+**職責**:在真正啟動傳輸前,將硬碟上散落的 TIFF/JPG 檔案、`.dat` 索引檔以及 `.ini` 設定檔,打包成單一的封裝檔以利傳輸。
+**核心實作特性**:
+* **ZIP 壓縮封裝**:
+ * 依賴 `TVCLZip` (VCLZip 模組)。
+ * `ZipMainFile`:讀取 `Context.dat` 等清單,將案件目錄下的所有影像與關聯的索引文字檔打包成 `Img.zip`。
+ * 包含檔案大小檢核邏輯:在打包完成後,檢查 ZIP 檔是否超過伺服器允許的上限 (`FMaxUploadSize`),若超過則阻擋上傳。
+* **ZIP 解壓縮處理**:
+ * 依賴 `VCLUnZip` 模組。
+ * `ExecuteUnZip` / `ExecuteUnZip_Pwd`:將從伺服器下載回來的 `OMRSet.zip`、`KeyinSet.zip` 或舊案件影像壓縮檔解壓縮至指定的工作目錄中,並支援帶密碼的解壓縮。
+
+---
+
+## 💡 未來重構與微服務化建議
+
+針對「安全傳輸與 API 通訊模組」,若未來系統架構演進,建議考量以下重構方向:
+
+1. **統一且標準化的 HTTP Client (捨棄舊版第三方庫)**:
+ 早期的 SecureBlackbox 雖然強大,但現代的開發環境 (如新版 Delphi 或 C#/Java/Node.js) 均已內建完善且高效的 `HttpClient`。建議將所有的 API 呼叫標準化為 RESTful API (JSON 格式),並使用原生的網路庫。
+2. **廢除 FTP,全面改用 HTTP(S) 分塊上傳 (Chunked Upload)**:
+ 目前系統需動態切換 HTTP 與 FTPS,增加了防火牆設定 (Port 21, Passive Ports) 與除錯的困難度。現代系統處理大檔上傳,主流做法是透過 HTTP/HTTPS 的 **分塊上傳 (Chunked Upload / Multipart)** 搭配斷點續傳機制,建議未來可逐步汰除 FTP 傳輸路徑。
+3. **非同步與背景傳輸 (Asynchronous Transfer)**:
+ 目前上傳時會透過 `DataLoading` 鎖死整個 UI (`Screen.Cursor := -11`),使用者必須枯等上傳完成。重構時應將 Transport Manager 放入獨立的 Thread 或背景 Service 中執行,並透過回呼 (Callback) 或事件 (Event) 更新進度條,提升使用者體驗。
+4. **Token-based 授權取代自訂加密**:
+ 目前依賴自訂的 `En_DecryptionStr_Base64` 在 URL 傳遞加密字串作為安全驗證。建議未來升級為標準的 **OAuth 2.0 (JWT Token)** 放在 HTTP Header 中進行授權,更加安全且符合現代 Web 規範。
diff --git a/doc/curtis/UI_View_Analysis.md b/doc/curtis/UI_View_Analysis.md
new file mode 100644
index 0000000..f6b4f93
--- /dev/null
+++ b/doc/curtis/UI_View_Analysis.md
@@ -0,0 +1,86 @@
+# UI 視圖與介面呈現模組 (UI View) 深度分析
+
+在 `CB_IMGPSScanImp.pas` 中,「UI 與介面呈現模組」主要負責與使用者的視覺互動,這是作為 ActiveX 控制項的核心表現形式。它管理了表單的佈局、多國語言切換、快捷鍵操作以及各種滑鼠拖拉 (Drag and Drop) 與捲動行為。
+
+以下是針對 UI View 模組的深度組成與分類分析:
+
+---
+
+## 1. 核心版面與容器管理 (Layout & Container Management)
+
+**職責**:定義整個 ActiveX 控制項的視覺區塊,並透過階層式的 Panel 進行排版管理,確保在不同解析度下能正確顯示。
+**核心實作特性**:
+* **ActiveX 窗體繼承**:`TCB_IMGPSScanX` 繼承自 `TActiveForm`,並實作 `ICB_IMGPSScanX` 介面,是所有 UI 元件的根容器。
+* **Panel 排版系統**:使用大量的 `TPanel` (如 `Panel1`, `Panel2`, `Panel9` 等) 與 `TSplitter` (如 `Splitter1`, `Splitter2`) 來分割畫面:
+ * **頂部/底部工具列**:放置各種操作按鈕 (`TBitBtn`, `TButton`)。
+ * **左側樹狀區**:放置文件結構清單 (`TreeView1`)。
+ * **右側工作區**:通常包含影像預覽或細節設定面板 (`Panel9`, `ScrollBox1`)。
+* **動態模式切換**:透過 `DisplayMode` 與 `GoViewMode` 根據不同的視圖模式 (VMode) 動態調整右側影像預覽區塊的排列方式 (如 1x1, 1x2, 2x2 等),並控制各 `imgp` (Panel) 的顯示與隱藏。
+
+## 2. 影像預覽與互動視窗 (Image Viewer & Interaction)
+
+**職責**:提供高效能的影像顯示功能,支援大圖縮放、拖曳平移、局部放大以及多頁縮圖並排顯示。
+**核心實作特性**:
+* **Envision 影像元件**:深度依賴 `EnImgScr` (TImageScrollBox) 來處理大型 TIFF/JPEG 影像的渲染與捲動。
+* **多圖預覽管理**:
+ * 主影像 (`ISB1`) 與縮圖陣列 (`ISB2` ~ `ISB8`)。
+ * 背景生成黑白影像 (`ISB_BW`) 供內部條碼辨識或影像處理使用,而不影響前端彩色顯示。
+ * 動態建立/釋放:`CreatePreViewISB` 與 `FreePreViewISB` 負責根據案件頁數動態產生縮圖物件。
+* **滑鼠行為模式 (Mouse Mode)**:
+ * 透過 `ViewMouseMode` 函式切換 `TImageScrollBox` 的狀態,例如:放大鏡 (`mmAmplifier`)、框選縮放 (`mmZoom`)、手形拖曳 (`mmDrag`)、旋轉 (`mmR90`, `mmR180`, `mmR270`) 或刪除 (`mmDelete`)。
+ * 對應工具列按鈕 (`FC0` ~ `FC6`) 的點擊事件 (`FC0Click` ~ `FC6Click`) 來切換這些游標模式。
+* **滑鼠與滾輪事件**:
+ * 處理自定義的滾輪捲動 (`WMMOUSEWHEEL`),同步捲動 `ScrollBox1` 或放大縮小影像 (`ZoomPercent`)。
+ * 處理影像上的點擊 (`ISBClick`) 與拖拉排序 (`ISBDragDrop`, `ISBDragOver`)。
+ * 在影像上繪製選取框 (`PaintShape`, `FreeShapeobj`)。
+
+## 3. 案件與文件樹狀檢視 (Case & Document TreeView)
+
+**職責**:以階層式樹狀結構呈現當前掃描或下載的「案件 -> 文件 -> 頁面」,並提供豐富的右鍵選單功能以管理這些節點。
+**核心實作特性**:
+* **TTreeView 結構維護**:
+ * `NewTreeNode`:頂層節點(如:新件、異動件)。
+ * `MyTreeNode1`:案件層級 (CaseID)。
+ * `MyTreeNode2`:文件層級 (DocNo/DocDir)。
+ * `MyTreeNode3`:表單/頁面層級 (FormID)。
+* **視覺狀態回饋**:依據節點的狀態改變圖示 (`ImageIndex`),例如:未配號、檢核失敗、完成檢核、或標記為被引用 (`GetUseCase`) 的文件。
+* **節點資料綁定與更新**:
+ * 利用 `DrawDocItem2` 根據實體的 `.dat` 設定檔重新長出整棵樹。
+ * 利用 `NewTreeNodeRefresh`, `MyTreeNode1Refresh` 等更新節點後方的筆數或頁數統計。
+* **右鍵選單與節點操作**:
+ * 根據選中的節點層級,動態顯示/隱藏 `PopupMenu1` 的選項 (`PopupMenu1Popup`)。
+ * 支援在樹狀圖上的拖拉移動 (`TreeView1DragDrop`) 以改變影像歸屬。
+
+## 4. 多國語言與本地化引擎 (I18N & Localization)
+
+**職責**:將 UI 介面上的所有寫死字串抽離,透過外部設定檔實現多國語言的動態切換。
+**核心實作特性**:
+* **語言檔載入**:在初始化時透過 HTTP/FTP 下載最新的語言包 (`Language.Lng` 至 `LngPath`)。
+* **動態介面翻譯**:`InitialLanguage` 函式。
+ * 利用 `TMemIniFile` 讀取語言檔。
+ * 遍歷表單上的所有元件 (`Components`),判斷其類型 (`TButton`, `TBitBtn`, `TMenuItem`, `TLabel`, `TListView`, `TRadioGroup` 等)。
+ * 將元件的 `Name` 作為 Key 去 Ini 檔中尋找對應的翻譯字串,並替換其 `Caption` 或 `Hint`。
+
+## 5. 系統狀態與進度回饋 (Status & Progress Feedback)
+
+**職責**:在進行耗時的網路傳輸、影像處理或資料庫比對時,鎖定 UI 並給予使用者明確的等待提示,避免重複操作。
+**核心實作特性**:
+* **全域 UI 鎖定 (`DataLoading`)**:
+ * 當執行耗時任務時,將滑鼠游標改為漏斗 (`crHourGlass`)。
+ * 停用主要的控制面板 (`Panel1.Enabled := False`, `Panel2.Enabled := False`)。
+ * 顯示中央的進度提示面板 (`Panel22` 或 `Panel8`)。
+* **動態文字更新**:透過 `Timer2` 定期在進度提示文字 (`ShowText`) 後方加上點號 (`...`),營造系統正在運作的視覺效果。
+* **狀態列 (`StatusBar1`)**:顯示當前版本號 (`GetCurrentVersionNo`)、登入使用者名稱、引用狀態,以及浮動授權 (License) 的剩餘額度。
+
+---
+
+## 💡 未來重構與微服務化建議
+
+若要將此「UI View 模組」進行現代化重構 (例如轉向 Web 介面或更清晰的架構),建議考量以下方向:
+
+1. **MVC / MVVM 架構解耦**:目前的程式碼將按鈕點擊事件 (Controller)、資料讀取 (Model) 與畫面更新 (View) 混雜在同一個 Pas 檔中。應將邏輯抽離,讓 UI 只負責「顯示資料」與「轉發命令」。
+2. **TreeView 虛擬化 (Virtualization)**:若案件內包含極多頁面,頻繁的 `DrawDocItem2` 清空並重建樹狀節點會導致效能低落。建議改用 Virtual TreeView 或資料綁定 (Data Binding) 的方式,只渲染可見節點。
+3. **分離多國語言引擎**:將 `InitialLanguage` 的邏輯獨立為一個全局的 `Translator` 服務,避免每個 Form 或 Frame 都需要自己實作載入邏輯。
+4. **Web 相容性評估**:
+ * 由於深切依賴 `TImageScrollBox` 的 Windows GDI 渲染與特定的滑鼠狀態 (`TMouseMode`),若要轉為 Web (HTML5/Canvas),需尋找或實作對應的 Web Image Viewer 套件。
+ * ActiveX 特有的 COM 介面 (`TActiveForm`, `safecall`) 將被淘汰,改以 WebSocket 或 REST API 提供狀態更新,前端由 React/Vue 等框架接手渲染。
diff --git a/doc/curtis/delphi_conventions.md b/doc/curtis/delphi_conventions.md
new file mode 100644
index 0000000..e068b7f
--- /dev/null
+++ b/doc/curtis/delphi_conventions.md
@@ -0,0 +1,249 @@
+# **Delphi 命名規範與風格指南 (Naming Conventions)**
+
+## **1. 大小寫敏感度 (Case Sensitivity)**
+
+在探討具體規範前,我們必須先釐清 Delphi 編譯器的特性:
+
+- **Delphi 是「大小寫不敏感」的 (Case-Insensitive):**
+
+ 對 Delphi 編譯器而言,CaseID、caseid、CASEID 甚至 cAsEiD 都是**完全相同**的變數。這與 C++, C#, Java, JavaScript (這些是 Case-sensitive) 有著根本上的不同。
+
+- **為什麼還需要規範?**
+
+ 既然編譯器不在乎,為什麼大家還是很嚴格遵守大小寫?因為**「人」在乎**。統一的大小寫規範(通常是 PascalCase)能極大提升程式碼的可讀性。
+
+- **何時大小寫「絕對」重要?**
+
+ 當 Delphi 與外部世界溝通時!例如:
+
+1. 呼叫 C/C++ 寫的 DLL 函數(如 Windows API)。
+2. 處理 JSON/XML 資料解析時。
+3. 將 ActiveX/OCX 元件提供給網頁端的 JavaScript 呼叫時(這也是為什麼你在 _TLB.pas 裡會看到像 caseno 這種全小寫的屬性,因為它是為了迎合 JS/Web 的習慣)。
+
+## **2. 常見的程式命名風格 (Casing Styles)**
+
+了解以下三種風格,有助於我們理解 Delphi 的選擇:
+
+1. **PascalCase (帕斯卡命名法)**:每個單字的首字母都大寫。
+- *範例*:CalculateTotal, UserName, CaseID
+- **Delphi 的最愛**:Delphi 絕大多數的命名都基於這個風格。
+1. **camelCase (駱駝命名法)**:第一個單字全小寫,後續單字首字母大寫。
+- *範例*:calculateTotal, userName, caseId
+- **Delphi 的應用**:偶爾用於區域變數(Local Variables),但在傳統 Delphi 中不如 Java/C# 常見。
+1. **snake_case (蛇形命名法)**:全小寫,單字間用底線 _ 分隔。
+- *範例*:calculate_total, user_name, case_id
+- **Delphi 的應用**:**極少使用**。通常只出現在早期的舊程式碼,或是為了與 C 語言庫(如 SQLite, LibVLC)保持一致時才會使用。
+
+## **3. Delphi 核心命名規範 (前綴字慣例)**
+
+Delphi 最具特色的就是使用**單一字母前綴**來標示該元素的「種類」或「作用域」。
+
+| **元素類型 (Type)** | **前綴** | **命名風格** | **範例與說明** |
+| --- | --- | --- | --- |
+| **類別 (Class/Type)** | **T** | PascalCase | TForm, TCustomer
+*(T 代表 Type,所有類別與自訂型別皆以此開頭)* |
+| **介面 (Interface)** | **I** | PascalCase | IUnknown, IScanner
+*(I 代表 Interface)* |
+| **例外 (Exception)** | **E** | PascalCase | EOutOfMemory, EFileNotFound
+*(E 代表 Exception)* |
+| **指標 (Pointer)** | **P** | PascalCase | PChar, PInteger
+*(P 代表 Pointer)* |
+| **私有欄位 (Field)** | **F** | PascalCase | FCaseID, FWidth
+*(F 代表 Field,僅存在於類別的 private/protected 區段)* |
+| **屬性 (Property)** | **無** | PascalCase | CaseID, Width
+*(對外公開的屬性,通常用來讀寫對應的 F 變數)* |
+| **方法參數 (Parameter)** | **A** | PascalCase | AOwner, ACaseID
+*(A 代表 Argument,用以避免與內部 Field 撞名)* |
+
+## **4. 變數與常數命名**
+
+- **區域變數 (Local Variables)**:
+- 通常使用 **PascalCase**,不加前綴。例如:ImageStream, TotalCount。
+- 迴圈計數器習慣使用大寫字母:I, J, K。
+- **全域變數 (Global Variables)**:
+- 盡量避免使用。若必須使用,部分開發者會加上 G 前綴(如 GSystemStatus)。
+- **常數 (Constants)**:
+- 現代 Delphi 傾向直接使用 PascalCase 配合列舉。部分開發者使用 c 前綴(如 cMaxRetries)。
+
+## **5. 列舉型別 (Enumerations) 的特殊規範**
+
+Delphi 對列舉型別有非常優雅的規範:**型別以 T 開頭,列舉值以該型別的 2~3 個字母縮寫作為小寫前綴。**
+
+- *範例*:
+
+ type
+
+ TTransMode = (tsHttp, tsFtp, tsNone);
+
+ TFormAlign = (alNone, alTop, alBottom, alLeft, alRight, alClient);
+
+
+## **6. 檔案與單元 (File & Unit) 命名**
+
+在 Delphi 中,檔案名稱(.pas)與程式碼內宣告的單元名稱(unit XXX;)**必須完全一致**。
+
+- **基本規則**:使用 **PascalCase**,避免使用空白與特殊字元。
+- **視覺化窗體 (Forms)**:單元檔名通常結尾加上 Frm、Form 或 UI。
+- **資料模組 (DataModules)**:單元檔名通常結尾加上 DM。
+
+## **7. 檔案命名後綴與副檔名解析 (File Extensions & Suffixes)**
+
+在 Delphi 的專案架構中,除了單元名稱外,副檔名與特定的檔名後綴也承載了重要的架構意義。
+
+### **7.1 檔名後綴 _TLB**
+
+當你開發或匯入 COM、ActiveX 或 Automation Server 時,Delphi IDE 會自動生成以 _TLB 結尾的檔案(例如 CB_IMGPSScan_TLB.pas)。
+
+- **意義**:TLB 是 **Type Library (類型庫)** 的縮寫。
+- **作用**:Type Library 本身是一個二進位檔案,用來跨語言描述 COM 元件的介面。Delphi 為了讓 Object Pascal 能呼叫這些介面,會將其反編譯成 .pas 程式碼,並自動加上 _TLB 後綴。
+- **⚠️ 核心規範**:**絕對不要手動修改 _TLB.pas 檔案的內容!** 只要你在 IDE 中重新整理 Type Library,這個檔案就會被完全覆蓋重寫。若要實作功能,應寫在對應的 _Imp.pas 或其他單元中。
+
+### **7.2 常見的 Delphi 副檔名**
+
+以下是 Delphi 專案中常見的副檔名及其具體用途:
+
+| **副檔名** | **類型** | **說明** |
+| --- | --- | --- |
+| **.pas** | 原始碼 (Source) | **Pascal Source File**。最常見的程式碼檔案(單元/Unit),包含介面宣告 (interface) 與實作邏輯 (implementation)。 |
+| **.dpr** | 專案檔 (Project) | **Delphi Project**。專案的主進入點,定義這是一個執行檔 (program) 還是程式庫 (library),並包含專案的啟動邏輯與引入單元列表。 |
+| **.dfm** | 介面檔 (Form) | **Delphi Form**。儲存視覺化窗體 (Form) 或資料模組 (DataModule) 上所有元件的屬性與佈局設定。一定與同名的 .pas 檔成對出現。 |
+| **.dcu** | 編譯檔 (Compiled) | **Delphi Compiled Unit**。.pas 檔案成功編譯後產生的二進位結果。最終連結器 (Linker) 會將這些 .dcu 打包成 EXE 或 DLL。 |
+| **.res** | 資源檔 (Resource) | **Compiled Resource File**。二進位資源檔,包含應用程式圖示 (Icon)、版本資訊或夾帶的檔案。通常在 .dpr 中用 {$R *.res} 編譯指令引入。 |
+| **.tlb** | 類型庫 (Type Lib) | **Type Library**。微軟 COM 標準的二進位檔案,用來描述 ActiveX 元件對外公開的介面、方法與屬性,供其他語言(如 C++, JS)參考呼叫。 |
+| **.ridl** | 介面定義 (RIDL) | **Restricted Interface Definition Language**。較新版 Delphi 用來取代舊式二進位 .tlb 的純文字介面定義檔。開發者可以透過文字或 IDE 編輯它,編譯時會自動生成對應的 .tlb 與 _TLB.pas。 |
+| **.ocx** | 控件擴充檔 | **OLE Control Extension**。本質上是一個特殊格式的 DLL(動態連結函式庫),內部包含了 ActiveX 控件。Windows 系統可以透過 regsvr32 註冊它,讓 IE 瀏覽器或其他應用程式嵌入使用。 |
+
+## **8. Delphi 架構與現代語言概念對應 (Architecture Mapping)**
+
+對於習慣 C#、Java、Python 或 JavaScript 的開發者,了解 Delphi 專屬的結構名詞如何對應到現代語言是非常重要的。
+
+### **8.1 Namespace (命名空間)**
+
+- **現代語言對應**:等同於 C# 的 namespace、Java 的 package,或是 C++ 的 namespace,用來組織程式碼並避免名稱衝突。
+- **Delphi 的對應**:
+- **早期 Delphi (如 Delphi 7/2007)**:沒有明確的 Namespace 關鍵字,**unit (單元) 本身就充當了扁平化的命名空間**。為避免撞名,開發者強烈依賴「前綴字」(例如 Indy 網路套件都以 Id 開頭,如 IdHTTP;Envision 影像套件以 En 開頭,如 EnScan)。
+- **現代 Delphi (XE2 以後)**:正式引入了 **Dotted Unit Names (點綴命名)** 作為 Namespace 的支援。例如原先的 SysUtils.pas 變成了 System.SysUtils.pas,Forms.pas 變成了 Vcl.Forms.pas。
+
+### **8.2 Class (類別)**
+
+- **現代語言對應**:等同於 C# / Java / TS 的 class。
+- **Delphi 的對應**:同樣使用 class 關鍵字,但在 Delphi 中必須宣告於 type 區塊之下。如前文所述,類別名稱慣例上**必須以大寫 T 開頭**(例如 TMainForm)。實體化時,Delphi 是呼叫建構子方法(如 TMyClass.Create),而不是使用 new 關鍵字。
+
+### **8.3 Unit (單元, .pas)**
+
+- **現代語言對應**:等同於 ES6 的 **Module (.js/.ts)**、Python 的 **Module (.py)**,或是 C/C++ 中 .h (標頭檔) 與 .cpp (原始檔) 的綜合體。
+- **Delphi 的對應**:unit 是 Delphi 程式碼封裝的最核心基礎。一個完整的 unit 會被劃分為兩個主要區塊:
+- **interface (介面區)**:等同於對外輸出的 API 或 Header,這裡宣告的型別與函式可透過 uses 關鍵字被其他檔案呼叫。
+- **implementation (實作區)**:等同於內部的私有邏輯實作。在這裡宣告的變數或函式,對外部檔案是完全隱藏的。
+
+### **8.4 Library (程式庫, .dpr)**
+
+- **現代語言對應**:等同於 C# 的 **Class Library 專案**、Node.js 的原生 C++ 附加元件,或 C/C++ 的 **Shared Library / 動態連結檔**。
+- **Delphi 的對應**:在專案原始檔中(.dpr),如果開頭宣告為 library(而非一般視窗程式的 program),代表它的編譯目標是一個不具獨立執行程序的主體,通常會編譯為 **.dll** 或 **.ocx**。這類專案主要透過 exports 關鍵字,將內部的函式暴露給作業系統或其他語言的程式(如 C++ 或網頁瀏覽器)來呼叫。
+
+
+## **9 Compiler Directive**
+
+在 Delphi (Object Pascal) 中,`{ }` 符號的意義取決於緊跟在 `{` 後面的第一個字元。這是一個非常基礎但關鍵的語法,讓我們來拆解你的疑問:
+
+---
+
+### 9.1 `{ }` 符號的基本意義:註解 (Comments)
+
+在最基本的情況下,`{ }` 是 **「區塊註解」**。編譯器會完全忽略裡面的內容。
+
+* **`{ TCB_IMGPSScanX }`**:這是一段 **註解**。
+ * **作用**:通常開發者寫這行是為了告訴讀程式碼的人:「接下來這一段程式碼是屬於 `TCB_IMGPSScanX` 類別的實作」。它對程式執行**沒有任何影響**。
+* **`TCB_IMGPSScanX`**:這是一段 **程式碼 (識別碼)**。
+ * **作用**:編譯器會去尋找名為 `TCB_IMGPSScanX` 的類別、型別或變數。如果沒定義,編譯就會報錯。
+
+---
+
+### 9.2 `{$ }` 符號的進階意義:編譯指令 (Compiler Directives)
+
+當 `{` 後面緊跟著 **`$`** 字元時,它就從「註解」變成了 **「編譯指令」**。這不是給人看的,而是**給編譯器下的指令**。
+
+#### 關於 `{$I filename}` (Include 指令)
+你看到的 `{$I ...}` 是 **Include Directive**。
+
+* **作用**:它的功能就像是編譯器的「複製貼上」工具。它告訴編譯器:「在編譯這行時,請先去把 `CB_IMGPSScanImp_UI.pas` 檔案裡的文字**原封不動地抓過來,塞到這個位置**,然後再繼續往下編譯」。
+* **目的**:這通常用來處理非常巨大的程式碼檔案。就像你之前的 `CB_IMGPSScanImp.pas` 檔案太長了,開發者把它拆成小檔案,最後用這種方式在主檔「匯合」。
+
+---
+
+### 9.3 解析你的範例語法
+
+你提到的這一段:
+`{$I CB_IMGPSScanImp_UI.pas}{$I CB_IMGPSScanImp_Scan.pas}...initialization`
+
+#### 這是在做什麼?
+這既不是定義,也不是宣告,更不是字串。它是一種 **「程式碼組合行為」**。
+
+1. **組合實作內容**:編譯器會依序讀入 `UI.pas`、`Scan.pas`、`Data.pas`、`Utils.pas`。這四個檔案裡放的通常是 `TCB_IMGPSScanX` 的各種 `procedure` 和 `function` 實作。
+2. **銜接初始化區段**:當上述所有檔案的內容都被「貼進來」後,程式碼剛好接到了 `initialization` 關鍵字。
+
+#### 語法邏輯如下:
+```pascal
+implementation
+
+// 編譯器開始貼上檔案
+[貼上 UI.pas 的內容]
+[貼上 Scan.pas 的內容]
+[貼上 Data.pas 的內容]
+[貼上 Utils.pas 的內容]
+
+// 貼完後,剛好銜接這支單元的初始化邏輯 (AxCtrl)
+initialization
+ TActiveFormFactory.Create(...);
+ SetLicenseKey(...);
+end.
+```
+
+### 總結
+* **`{ ... }`** = 註解(編譯器不看)。
+* **`{$I ...}`** = 編譯器指令(叫編譯器去別的檔案搬程式碼過來貼上)。
+* **為什麼這樣寫?** 這是為了讓主檔保持簡潔。主檔只負責「宣告結構」和「啟動初始化」,而「具體的細節邏輯」則被藏在那些被 Include 的檔案裡。
+
+
+## 10. 註解語法與風格慣例 (Comments Style)
+
+Delphi 提供三種主要的註解方式,以及一些開發者社群常用的視覺化風格:
+
+### 10.1 單行註解 (`//`)
+
+- **用法**:從 `//` 開始到該行結束。
+- **視覺強調 (`////`)**:
+ - 你在源碼中看到的 `////` 語法上等同於 `//`。
+ - **開發者意圖**:通常用於**「標題化」**或**「強力分隔」**。多個斜線能在視覺上形成橫條效果,幫助開發者在快速捲動程式碼時一眼認出關鍵區塊(例如:`//// ***** 預設區 ***** ////`)。
+
+### 10.2 區塊註解 (`{ }`)
+
+- **用法**:被 `{ }` 包圍的所有文字。
+- **特點**:常用於長篇說明的標註,或是在調試時暫時關閉一整段程式碼。
+- **編譯指令**:若開頭為 `{$`(如 `{$R *.DFM}`),則代表它是給編譯器的指令,而非一般註解。
+
+### 10.3 替代區塊註解 (`(* *)`)
+
+- **用法**:由 `(*` 開始到 `)` 結束。
+- **主要用途 (註解嵌套)**:當你想要註解掉一段已經包含 `{ }` 註解的程式碼時,Delphi 規定 `{ }` 不能包在另一對 `{ }` 裡面,此時必須改用 `(* ... *)` 來包裹,才能正確註解。
+
+### 10.4 文件化註解 (`///` XML Documentation)
+
+- **用法**:在方法上方使用連續三個斜線。
+- **作用**:現代 Delphi IDE (XE 以後) 會解析這類註解,並在鼠標懸停於方法名上時顯示提示說明(類似 JavaDoc 或 C# XML Doc)。
+
+### 10.5 分隔線風格示例
+
+在大型檔案(如 `CB_IMGPSScanImp.pas`)中,常用註解來劃分功能界線:
+
+```
+// ********************************************************************* //
+// 這是區塊分隔線風格,常用於自動生成的 TLB 檔
+// ********************************************************************* //
+
+{-----------------------------------------------------------------------}
+{ 這是另一種常見的手寫分隔線風格 }
+{-----------------------------------------------------------------------}
+```
+
+
diff --git a/doc/curtis/index.md b/doc/curtis/index.md
new file mode 100644
index 0000000..6bb2376
--- /dev/null
+++ b/doc/curtis/index.md
@@ -0,0 +1,15 @@
+
+## TableOfContent
+- [IO_說明.md](IO_%E8%AA%AA%E6%98%8E.md)
+- [ScanImp_分析.md](ScanImp_%E5%88%86%E6%9E%90.md)
+- [介面實作.md](%E4%BB%8B%E9%9D%A2%E5%AF%A6%E4%BD%9C.md)
+- [delphi_專案必讀.md](delphi_%E5%B0%88%E6%A1%88%E5%BF%85%E8%AE%80.md)
+- [EnScan_拆解.md](EnScan_%E6%8B%86%E8%A7%A3.md)
+
+
+
+- 各生命周期 or diagram
+- Remote/Local IO 方法
+- Remote/Local IO 抽象介面
+- OCX 抽像介面
+-
diff --git "a/doc/curtis/remote_\347\233\270\351\227\234\346\226\271\346\263\225.md" "b/doc/curtis/remote_\347\233\270\351\227\234\346\226\271\346\263\225.md"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/doc/curtis/remote_\347\233\270\351\227\234\346\226\271\346\263\225.md"
diff --git "a/doc/curtis/\345\210\206\346\236\220_\345\260\232\351\200\262\350\241\214\344\270\255.md" "b/doc/curtis/\345\210\206\346\236\220_\345\260\232\351\200\262\350\241\214\344\270\255.md"
new file mode 100644
index 0000000..a454c84
--- /dev/null
+++ "b/doc/curtis/\345\210\206\346\236\220_\345\260\232\351\200\262\350\241\214\344\270\255.md"
@@ -0,0 +1,830 @@
+
+
+# **相依套件分析報告**
+
+本報告針對 ActiveX 元件核心實作檔 CB_IMGPSScanImp.pas 進行功能解構,並分析其與第三方套件的綁定關係,以作為後續維護或現代化升級之參考。
+
+## **壹、 依功能拆分模組與第三方套件綁定分析**
+
+根據原始碼結構,CB_IMGPSScanImp.pas 是一個將介面、硬體、網路與業務邏輯高度耦合的「上帝物件 (God Object)」。若要進行重構或拆件,建議依據以下五個核心模組進行解耦:
+
+### **1. 硬體掃描控制模組 (Scanner Controller)**
+
+- **功能描述**:負責與實體掃描機溝通,處理 TWAIN 介面初始化、設定掃描參數(DPI、色彩、雙面)、觸發掃描指令,以及接收掃描完成的記憶體影像 (DibHandle)。
+- **關鍵方法**:initkscan、StatrTwainScan、OnAcquire、PageEnd、PageDone。
+- **第三方套件綁定 (強綁定)**:
+- 依賴 **Envision Imaging SDK** (EnScan) 進行 TWAIN 驅動控制。
+- 依賴 EnMisc 處理底層記憶體或雜項運算。
+
+### **2. 影像處理與轉換模組 (Image Processor)**
+
+- **功能描述**:負責對擷取到的原始影像進行後製處理,包括:裁切(如 A3 裁 A4)、去斜 (Deskew)、旋轉、二值化 (轉黑白)、格式轉換 (轉 TIFF/JPEG),以及讀取影像上的條碼。
+- **關鍵方法**:ImageReSize_FormID、CheckNeedCrop、DeskewImg、ConvertToBW。
+- **第三方套件綁定 (強綁定)**:
+- 依賴 **Envision Imaging SDK** (EnTifGr, EnDiGrph) 進行 TIFF (CCITT Group 4) 壓縮與 DIB 物件封裝。
+- 依賴 **MPS Barcode** (mpsBarco, BarcodesFinder) 進行影像條碼掃描與解析。
+
+### **3. 安全傳輸與 API 通訊模組 (Transport Manager)**
+
+- **功能描述**:負責將掃描並壓縮後的檔案上傳至伺服器,或從伺服器下載檔案。同時處理與後端 Java Servlet 的參數交換(如校時、取得 FTP 資訊、更新案件狀態)。
+- **關鍵方法**:upFile、dnFile_Get、ProcessServlet_Get、GetServerDate、GetftpInfo。
+- **第三方套件綁定 (強綁定)**:
+- 依賴 **SecureBlackbox** (SBSimpleSSL, SBHTTPSClient, SBSimpleFTPS 等) 處理 HTTPS/FTPS 安全加密通訊。
+- 依賴 **Indy** (IdHashMessageDigest) 產生檔案的 MD5 檢核碼。
+- 依賴自訂/第三方加密庫 (Encryp) 處理字串加解密。
+
+### **4. 業務邏輯與資料解析模組 (Business Logic & Parser)**
+
+- **功能描述**:專案核心的領域邏輯,包含接收網頁端傳入的參數字串進行解析、定義文件歸類邏輯(由條碼推導文件類型)、OMR (光學標記辨識) 檢核定義等。
+- **關鍵方法**:SetSQLData (負責解析傳入的長字串至 TStringList)、GetSQLData、FormCode2DocNo、OMRCheckCase。
+- **第三方套件綁定 (中度綁定)**:
+- 依賴 **Xmltool** 解析 XML 格式的 OMR 座標定義。
+- 依賴 **VCLZip** (VCLZip, VCLUnZip) 將多個影像檔打包成 ZIP 進行單一傳輸。
+
+### **5. UI 與介面呈現模組 (UI View)**
+
+- **功能描述**:負責 ActiveX 控制項的視覺化介面,包含左側的樹狀文件清單 (TreeView)、右側的影像預覽區 (ScrollBox),以及按鈕與多國語言切換。
+- **關鍵方法**:InitialLanguage、各類 OnClick 事件。
+- **第三方套件綁定 (輕度綁定)**:
+- 依賴 **Envision Imaging** (EnImgScr) 作為支援大影像拖曳的滾動視窗。
+- 依賴 PJMenuSpeedButtons 作為自訂外觀的按鈕元件。
+
+## **貳、 第三方套件功能總覽**
+
+為達成上述複雜的業務需求,本專案引入了多個 Delphi 著名的第三方套件。以下為各套件的大致功能說明:
+
+### **1. Envision Imaging SDK (前綴 En)**
+
+這是一套專為 Delphi 設計的高效能影像與 TWAIN 處理套件,在金融與保險業的文件電子化系統中非常常見。
+
+- **EnScan**:封裝了 TWAIN 協定,讓程式能直接控制實體掃描機,控制進紙、解析度與雙面掃描。
+- **EnDiGrph (TDibGraphic)**:封裝 Windows 底層的 DIB (Device Independent Bitmap) 記憶體句柄,讓開發者能像操作一般圖片一樣操作掃描出來的原始資料。
+- **EnTifGr**:專門處理 TIFF 影像格式。銀行業愛用 TIFF 是因為它支援「多頁」且黑白壓縮率極高 (Group 4 Fax Compression)。
+- **EnImgScr**:提供 TImageScrollBox 視覺元件,用來平滑顯示並縮放超大尺寸的掃描圖檔。
+- **EnMisc**:提供影像處理所需的底層輔助數學或資料轉換函式。
+
+### **2. SecureBlackbox (前綴 SB)**
+
+由 EldoS (後被 /n software 收購) 開發的強大安全通訊與加密套件。由於早期 Delphi (D7~D2007) 內建網路庫缺乏完善的 SSL/TLS 支援,此套件被廣泛用於補強安全性。
+
+- **SBHTTPSClient / SBSimpleSSL**:實作了完整的 HTTPS 用戶端通訊協定,用來安全地上傳檔案或呼叫 Servlet API。
+- **SBSimpleFTPS**:支援 FTP over SSL (FTPS) 的安全檔案傳輸。
+- **SBWinCertStorage / SBX509**:處理 Windows 系統內的憑證儲存區,以及 X.509 數位憑證的驗證(例如確認銀行伺服器的 HTTPS 憑證是否合法)。
+
+### **3. MPS Barcode & BarcodesFinder**
+
+- **功能**:這是一套條碼識別引擎。
+- **專案應用**:在掃描過程中(如 PageDone 或 OnAcquire 階段),它會掃描圖片特定區域尋找一維或二維條碼。讀取到的條碼值會被用來決定這張影像屬於哪一種「文件表單」(FormCode),進而實現自動分類歸檔。
+
+### **4. VCLZip (VCLZip, VCLUnZip)**
+
+- **功能**:老牌的 Delphi ZIP 壓縮元件。
+- **專案應用**:為了節省網路頻寬與減少伺服器連線次數,掃描完成的多張 TIFF/JPG 檔案會被打包成一個 .zip 檔後,再一次性上傳至伺服器。
+
+### **5. Indy Components (前綴 Id)**
+
+- **IdHashMessageDigest / idHash**:Delphi 內建的 Internet Direct (Indy) 函式庫。
+- **專案應用**:在此專案中被用來計算檔案或字串的 **MD5 Hash (雜湊值)**。通常用於確保檔案上傳過程沒有損壞,伺服器比對 MD5 一致才算上傳成功。
+
+### **6. 其他工具 (Tools & Utils)**
+
+- **Xmltool**:負責讀寫 XML 檔案。銀行經常將表單的 OMR (光學標記辨識) 檢核座標或參數寫成 XML 設定檔,透過此工具讀入系統。
+- **Encryp**:這可能是開發商自訂或第三方的輕量級加密單元,用來加密本機設定檔 (.ini) 內的敏感資訊或混淆網頁傳入的參數。
+
+# **核心源碼與物件實作解析**
+
+本文件針對 CB_IMGPSScanImp.pas 中的核心方法與隱藏物件進行原始碼級別的邏輯拆解與推導。
+
+## **壹、 核心方法源碼說明**
+
+### **1) TCB_IMGPSScanX.GetCurrentVersionNo**
+
+- **功能描述**:取得目前 OCX 元件的版本號。這通常提供給網頁端的 JavaScript 呼叫,用來判斷客戶端的 OCX 是否需要觸發更新下載。
+- **實作推導與底層 API 說明**:
+
+ 在 Delphi 中,若要動態讀取編譯進 OCX 的 VS_VERSION_INFO 資源,標準作法是呼叫一系列的 Windows API。這段實作通常包含以下三個關鍵概念:
+
+1. **HInstance (實體句柄)**:
+- 這是 Delphi 提供的一個全域變數,代表目前載入記憶體中的模組(即這個 OCX 檔)的「實體句柄 (Instance Handle)」。
+- 在 Windows 作業系統中,當一個執行檔 (EXE) 或動態連結檔 (DLL/OCX) 被載入記憶體時,會獲得一個記憶體基底位址,HInstance 就是指向這個位址的指標。Windows 需要這個值來識別「你要操作的是哪一個載入的模組」。
+1. **GetModuleFileName 的作用**:
+- 這是一個 Windows API。它的作用是利用前面提到的 HInstance,向作業系統反查出這個模組在硬碟上的**「完整實體檔案路徑」**(例如:C:\Windows\Downloaded Program Files\CB_IMGPSScan.ocx)。
+- 因為我們需要讀取檔案本身的版本資訊,程式必須先知道「我自己到底存放在硬碟的哪裡」。
+1. **後半段 VerQueryValue 的運作邏輯**:
+
+ 取得檔案路徑後,讀取版本資訊會經過三部曲,而 VerQueryValue 是最後負責「解析」的關鍵:
+
+- **Step 1 (GetFileVersionInfoSize)**:先問 Windows 這個檔案的版本資訊區塊有多大。
+- **Step 2 (GetFileVersionInfo)**:把整塊版本資訊的二進位原始資料 (Raw Data) 完整讀進一段記憶體緩衝區中。
+- **Step 3 (VerQueryValue)**:因為剛剛讀進來的是一包無法直接閱讀的二進位資料,VerQueryValue 的作用就是**「在這包資料中進行精準查詢」**。透過傳入特定的查詢路徑(例如傳入 \ 可以取得包含主版號、次版號的 VS_FIXEDFILEINFO 結構體;或是傳入特定語系代碼如 \StringFileInfo\040404E4\FileVersion),作業系統會幫你把二進位資料解析成我們需要的字串或數字版本號(如 1.0.3.5)。
+
+### **2) TCB_IMGPSScanX.ActiveFormCreate**
+
+- **功能描述**:這是 ActiveX 視覺化窗體 (Form) 的生命週期起點。當 IE 瀏覽器或應用程式載入這個 OCX 時,首先觸發的初始化事件。
+- **實作推導**:
+
+ 它會負責初始化全域變數、設定第三方元件的預設值、並建立暫存資料夾。
+
+ ```pascal
+ procedure TCB_IMGPSScanX.ActiveFormCreate(Sender: TObject);
+ begin
+ // 1. 預設變數初始化
+ Def_DeviceDelete := True;
+ Def_ScannerReverse := False;
+
+ // 2. 建立本機暫存目錄
+ ForceDirectories('C:\Temp\IMGPSScan');
+
+ // 3. UI 語系初始化
+ InitialLanguage;
+ end;
+ ```
+
+
+### **3) TCB_IMGPSScanX.StatrTwainScan**
+
+- **功能描述**:啟動掃描機的 TWAIN 介面,開始進紙或掃描。(註:Statr 應為 Start 的早期拼字錯誤,這在舊專案中很常見)。
+- **實作推導**:
+
+ 這個方法會讀取網頁傳進來的參數(如 DPI、色彩),設定給 Scanner 物件,然後發出擷取指令。
+
+ ```pascal
+ procedure TCB_IMGPSScanX.StatrTwainScan;
+ begin
+ // 設定解析度與顏色
+ Scanner.Resolution := StrToIntDef(Fimgdpi, 200);
+ if Fscancolor = 'C' then
+ Scanner.PixelType := ptColor
+ else
+ Scanner.PixelType := ptGray;
+
+ // 啟動掃描 (會喚起實體掃描機)
+ Scanner.Acquire;
+ end;
+ ```
+
+
+### **4) TCB_IMGPSScanX.OnAcquire 與資料流物件**
+
+- **功能描述**:這是 Scanner (EnScan) 最核心的事件。當掃描機成功掃完「一張」影像並傳入電腦記憶體時,會觸發此事件。
+- **源碼邏輯推導**:
+
+ ```pascal
+ procedure TCB_IMGPSScanX.ScannerAcquire(Sender: TObject; DibHandle: THandle; var Handled: Boolean);
+ var
+ MyStream: TMemoryStream;
+ MyGraphic: TDibGraphic;
+ begin
+ // 1. 將 DibHandle 轉換為 Delphi 影像物件
+ MyGraphic := TDibGraphic.Create;
+ MyGraphic.Handle := DibHandle;
+
+ // 2. 影像處理 (如去斜、黑白轉換)
+
+ // 3. 存入記憶體串流或實體檔案
+ // ...
+ end;
+ ```
+
+- **三大核心資料物件解釋**:
+1. **DibHandle**:這是 Windows 底層的「全域記憶體句柄 (Global Memory Handle)」。掃描機驅動把圖片放在記憶體裡,給你這個代號。你必須透過 TDibGraphic 來「解讀」這塊記憶體。
+2. **TMemoryStream**:**記憶體串流**。它的作用像是一塊存在 RAM 裡的虛擬硬碟。掃描後的圖檔在還沒存到實體硬碟前,會先放在這裡進行格式轉換 (如轉成 JPEG) 或進行 MD5 計算,因為在記憶體中操作速度最快。
+ - **DeleteStm : TMemoryStream 的逐行操作說明**:
+ 在 `OnAcquire` 事件中,`DeleteStm` 主要用於「空白頁判定」。其源碼邏輯如下:
+
+ ```pascal
+ // 判定是否啟動空白頁刪除功能
+ if Def_DeviceDelete then
+ begin
+ // 1. 在 Heap 記憶體中建立一個暫存串流物件
+ DeleteStm := TMemoryStream.Create;
+ try
+ // 2. 將當前掃描到的影像物件 (MyGraphic) 寫入記憶體串流
+ // 這會根據 TIFF G4 等格式進行壓縮,產生實際的檔案位元組資料
+ MyGraphic.SaveToStream(DeleteStm);
+
+ // 3. 核心判定:檢查該影像在記憶體中所佔用的位元組大小 (Size)
+ // 若小於預設門檻值 (Def_DeviceDeleteSize, 如 3072 Bytes)
+ if DeleteStm.Size < Def_DeviceDeleteSize then
+ begin
+ // 4. 若符合空白頁特徵,則不進行存檔動作,直接跳出此 Procedure
+ // 並告知掃描控制項此頁已處理完畢 (Handled := True)
+ Handled := True;
+ Exit;
+ end;
+ finally
+ // 5. 無論是否為空白頁,操作結束後必須釋放記憶體,避免 Memory Leak
+ DeleteStm.Free;
+ end;
+ end;
+ ```
+
+ -
+3. **TFileStream**:**檔案串流**。用來直接對硬碟讀寫資料。當確認影像無誤後,會透過 TFileStream 將 TMemoryStream 的內容真實地寫入 C:\Temp\...\001.tif 中。
+
+### **5) TCB_IMGPSScanX.FindISB2View**
+
+- **功能描述**:用來在畫面上尋找並更新用來預覽圖片的元件。
+- **名詞解釋**:**ISB 代表 ImageScrollBox**。
+
+ 這對應到 uses 區段中的 EnImgScr 套件。TImageScrollBox 是 Envision 提供的一個 UI 元件,專門用來顯示超出螢幕大小的掃描圖檔,支援平滑拖曳與縮放。這個方法通常用來把剛掃描完的 DibHandle 餵給畫面上的 ISB 元件顯示。
+
+
+### **6) TCB_IMGPSScanX.GetNoNameCase**
+
+- **功能描述**:處理「無案號」或「未知歸屬」的掃描件。
+- **源碼實作逐行說明**:
+
+ 此方法透過迴圈尋找一個尚未被使用的目錄名稱(格式為「未配號 + 四位數字」)。
+
+
+```pascal
+Function TCB_IMGPSScanX.GetNoNameCase(Path:String):String; // 取未配號XXXX
+var
+ i : Integer; // 宣告迴圈計數器
+begin
+ // 1. 啟動一個從 1 到 9999 的迴圈,尋找可用的索引值
+ for i := 1 to 9999 do
+ begin
+ // 2. 檢查特定路徑下的目錄是否已存在
+ // _Msg('未配號'):取得「未配號」字串(可能具備多國語言處理)
+ // Add_Zoo(i, 4):將數字 i 補齊為 4 位數(例如 1 變為 0001)
+ if Not DirectoryExists(Path + _Msg('未配號') + Add_Zoo(i, 4)) then
+ begin
+ // 3. 若該目錄不存在,代表此名稱可用,設定 Result 並跳出迴圈
+ Result := _Msg('未配號') + Add_Zoo(i, 4);
+ Break; // 找到第一個可用的名稱後立即停止搜尋
+ end;
+ end;
+end;
+```
+
+### **7) TCB_IMGPSScanX.SetSQLData 與 8) GetSQLData**
+
+這兩個方法是 OCX 與網頁 (JS) 溝通的雙向橋樑。
+
+- **SetSQLData (網頁 -> OCX)**:接收由網頁傳來的設定字串(通常用 | 或 , 分隔,例如 192.168.1.1|L12345678|200|C),在內部將字串切開 (Split),並分別賦值給 ServerIP, FCaseID, Fimgdpi, Fscancolor 等內部變數。
+- **GetSQLData (OCX -> 網頁)**:將 OCX 內部的處理結果(例如:UploadSuccess|3|0 代表上傳成功、共 3 頁、0 錯誤),組合成一個長字串後回傳給網頁端的 JS 進行後續的頁面跳轉或提示。
+
+### **8) TCB_IMGPSScanX.GetDefScanIni**
+
+- **功能描述**:取得並套用掃瞄參數的預設值與自訂設定。
+- **源碼實作解析**:
+ - **硬編碼預設值 (Hardcoded Defaults)**:
+
+ 程式一開始會先寫死一組標準值,例如 Def_ScanDpi := 300 (預設 300 DPI)、Def_DeviceDeleteSize := 3072 (空白頁判定門檻為 3KB)。
+
+ - **動態配置覆蓋 (Dynamic Overriding)**:
+
+ 透過 for i := 0 to WORK_INF_List.Count - 1 do 迴圈遍歷設定檔清單。使用 GetSQLData 取得參數代號 (PARA_NO) 與內容 (PARA_CONTENT)。
+
+- **屬性設定對照表**:
+
+ 下表整理了此方法中設定的所有關鍵屬性、其對應的參數代號及功能說明。
+
+ | **屬性名稱 (內部變數)** | **對應 PARA_NO** | **PARA_CONTENT 處理方式(GetSQLData)** | **功能說明** |
+ | --- | --- | --- | --- |
+ | **Def_DeviceDelete** | SCAN_BLANKDEL_USE | 'Y' -> True, Else -> False | 空白頁自動刪除開關。 |
+ | **Def_DeviceDeleteSize** | SCAN_BLANKDEL_SIZE | StrToInt (若空則 0) | 空白頁判定門檻 (Bytes)。 |
+ | **Def_ScannerReverse** | SCAN_REVERSE | 'Y' -> True, Else -> False | 影像是否反相。 |
+ | **Def_BoardClear** | SCAN_BOARDCLEAR | 'Y' -> True, Else -> False | 是否清除影像黑邊。 |
+ | **Def_ScanDpi** | SCAN_DPI | StrToInt (若空則 300) | 掃描解析度。 |
+ | **Def_ScanDuplex** | SCAN_DUPLEX | 'Y' -> True, Else -> False | 是否啟用雙面掃描。 |
+ | **Def_ScanRotate** | SCAN_ROTATE_MODE | '0'->0, '1'->270, '2'->180, '3'->90 | 掃描旋轉角度映射。 |
+ | **Def_ScanDeskew** | SCAN_DESKEW | 'Y' -> True, Else -> False | 是否自動矯正傾斜。 |
+ | **Def_ScanImgSetUse** | SCAN_IMGSET_USE | 'Y' -> True, Else -> False | 是否使用亮度/對比設定。 |
+ | **Def_ScanBright** | SCAN_BRIGHT | StrToInt (限制 -255~255) | 亮度數值。 |
+ | **Def_ScanContrast** | SCAN_CONTRAST | StrToInt (限制 -255~255) | 對比數值。 |
+ | **Def_ScanImgShowMode** | SCAN_SHOW_MODE | '0','1','2' 對應模式 | 影像顯示/縮放模式。 |
+ | **ScanDenialTime** | CASE_IN_TIME | 直接存為 String | 進件截止時間限制。 |
+ | **ScanDenialHint** | SCAN_HINT | 直接存為 String | 掃描畫面提示字串。 |
+ | **NoSaveBarCodeList** | NO_SAVE_FORM_ID | CommaText := Value | 不存檔之表單代號清單。 |
+ | **ImagePath** | LOCAL_PATH | 直接存為 String | 本機端暫存路徑。 |
+ | **GuideFormIDList** | GUIDEFORMID | CommaText := Value | 導引頁表單 ID 清單。 |
+ | **DivPageFormIDList** | DIVPAGEFORMID | CommaText := Value | 分案頁表單 ID 清單。 |
+ | **FJpgCompression** | FILE_COMPRESSION | StrToInt | JPG 轉 TIF 壓縮比。 |
+ | **FMaxUploadSize** | MAX_UPLOAD_SIZE | 直接存為 String | 上傳大小限制 (MB)。 |
+
+## **貳、 記憶體直接操作實作清單**
+
+以下條列專案中直接涉及記憶體操作的程式區段:
+
+### **記憶體操作對應位置表**
+
+| **記憶體操作對象** | **所屬 Function / Procedure** | **關鍵操作關鍵字 / 代碼** | **記憶體特性說明** | 註記 |
+| --- | --- | --- | --- | --- |
+| **HInstance** | GetCurrentVersionNo | GetModuleFileName(HInstance, ...) | 模組載入位址。 | 增API版本號 |
+| **資源緩衝區** | GetCurrentVersionNo | VerQueryValue, GetFileVersionInfo | 透過 Pointer 進行二進位搜尋。 | 增API版本號 |
+| **DibHandle** | onAcquire | MyGraphic.Handle := DibHandle; | Windows 全域記憶體句柄轉移。 | 改套件實作/Rust |
+| **TMemoryStream** | onAcquire | MemoryStream.Write, .Read | Heap Memory 內部二進位操作。 | |
+
+## **參、 遺失物件反推與說明**
+
+你提到在原始碼中找不到 _DelTree 和 Scanner 的實作,這是因為它們屬於以下兩種情況:
+
+### **1) TCB_IMGPSScanX._DelTree**
+
+- **這是一個自訂的私有輔助函式 (Private Helper)**。
+- **功能**:它的名稱源自 DOS 時代的指令 deltree(刪除整個目錄樹)。在 ActiveX 中,當上傳伺服器成功後,必須清空 C:\Temp\案件編號\ 裡的所有暫存圖檔與資料夾以釋放空間,並防止資料外洩。
+- **實作原理**:由於早期的 Delphi 沒有內建遞迴刪除目錄的單一指令,開發者通常會自己寫一個 _DelTree,裡面使用 FindFirst, FindNext 找出所有檔案並用 DeleteFile 刪除,最後用 RemoveDir 砍掉資料夾。
+
+### **2) Scanner**
+
+- **這是一個視覺化/非視覺化的第三方元件實例 (Component Instance)**。
+- **為何找不到宣告?** 因為在 Delphi 中,如果你是透過 IDE 的工具箱 (Tool Palette) 將 TEnScan 元件直接拖拉到窗體 (Form) 上,IDE 會自動把它寫在 .dfm 檔裡,並在 TCB_IMGPSScanX 類別的 published 區段自動產生一行 Scanner: TEnScan;。
+- **功能**:它就是 **Envision SDK** 裡用來與 TWAIN 硬體溝通的靈魂核心。所有的掃描屬性 (Scanner.Resolution) 與方法 (Scanner.Acquire) 都是對這個物件進行操作。
+
+---
+
+# **IO 路徑與檔案操作分析**
+
+本報告詳列了 CB_IMGPSScanImp.pas 檔案中定義的所有 IO 相關變數,以及執行目錄與檔案管理的關鍵方法,並定義了抽像化所需的介面原型。
+
+## **壹、 關鍵路徑與檔案變數 (Variables)**
+
+程式中定義了多個全域或私有欄位,用來追蹤檔案在硬碟上的實體位置。
+
+### **1. 核心路徑變數與動態組合邏輯**
+
+| **變數名稱** | **類型** | **組合邏輯 (Combination Logic)** | **用途說明** |
+| --- | --- | --- | --- |
+| **ImagePath** | String | WORK_INF 的 LOCAL_PATH 參數值 | **本機基礎根路徑**。所有暫存資料的起點。 |
+| **ScaniniPath** | String | ImagePath + FWork_No + '\' + FUserUnit + '\' | **設定檔存放區**。區分作業別與單位。 |
+| **ImageSavePath** | String | 同 ImagePath (初期) 或隨 FMode 變動 | **影像儲存基準路徑**。 |
+| **ScanPath** | String | ImageSavePath + ScanCaseno + '\' + ScanDocdir + '\' | **當前掃描實體目錄**。指向最末層的影像資料夾。 |
+| **TransPath** | String | ImageSavePath + CaseID + '\Upload\' | **準備上傳區**。在傳送前將檔案結構扁平化組合於此。 |
+| **DisplayPath** | String | ImageSavePath + NowCaseNo + '\' | **預覽基準目錄**。用於 UI 點選樹狀圖時讀取特定案件資料。 |
+| **LngPath** | String | GetLocalAppDir(Handle) + 'MPS\CB_IMGPS\' | **應用程式資源路徑**。存放在使用者設定檔目錄以避開權限問題。 |
+| **CheckXmlPath** | String | ImagePath + 'OMRSITE\' | **OMR 規則暫存區**。存放從伺服器同步下來的 XML 定義。 |
+| **SamplePath** | String | ImagePath + 'Sample\' + FWork_No + '\' | **範本影像存放區**。按作業別區分。 |
+| **SitePath** | String | ImagePath + 'Site\' | **登打定位存放區**。 |
+| **FFtpRootPath** | String | 透過伺服器回傳值動態設定 | **FTP 伺服器根路徑**。指定在遠端 FTP 伺育器上存放影像檔的起始位址。 |
+
+### **2. 檔案名稱變數 (Filenames)**
+
+| **變數名稱** | **類型** | **用途說明** |
+| --- | --- | --- |
+| **ScanSaveFilename** | String | 下一張掃描影像預定的檔名(通常包含 FormID)。 |
+| **PEFileName** | String | 在 PageEnd 階段確定的最終完整檔案路徑。 |
+| **AttName** | String | **附件目錄名稱**。根據 FIs_In_Wh 決定為 Attach 或 S_Attach。 |
+| **Ext** | String | 副檔名。預設為 .tif,彩色/灰階模式下可能切換為 .jpg。 |
+
+## **貳、 關鍵 IO 操作方法 (Methods)**
+
+以下為需要進行抽像化設計的核心 IO 方法。
+
+### **1. 目錄管理 (Directory Management)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| _DelTree | 遞迴刪除整個目錄樹 | 上傳成功後清空暫存、模式切換初始化目錄 | RemoveDirRecursive(Path) |
+| Str2Dir / ForceDirectories | 確保路徑以 \ 結尾並建立路徑 | 初始化或掃描前建立資料夾 | EnsureDirExists(Path) |
+| GetNoNameCase | 搜尋尚未配號的臨時目錄 | 在本機搜尋如 未配號0001 到 9999 的可用路徑 | FindNextAvailablePath(Pattern) |
+| GetLocalAppDir | 取得 Windows %LocalAppData% 路徑 | 確保在現代 Windows 系統中有權限寫入語言檔與 Log | GetBaseStoragePath() |
+
+### **2. 存在性檢查與搜尋 (Existence & Search)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| FileExists | 檢查指定路徑檔案是否存在 | 在載入 .dat、.ini 或影像前進行安全檢查 | IsFilePresent(Path) |
+| DirectoryExists | 檢查指定路徑資料夾是否存在 | 在建立掃描目錄或上傳前確認結構完整性 | IsDirPresent(Path) |
+| FindFirst / FindNext | 搜尋符合特定格式的檔案 | 取得實體檔案大小 (FileRec.Size) 或遞迴搜尋檔案 | ListFiles(Path, Pattern) / GetFileInfo(Path) |
+
+### **3. 檔案生命週期與刪除 (File Lifecycle & Deletion)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| ReSortFileName | 影像重新編序命名 | 刪除或插入影像後,修正 001_xxx 等序號連續性 | RenameFile(Old, New) |
+| DeleteImageFile | 刪除實體影像檔 | 單張影像刪除並觸發 .dat 內容同步更新 | DeleteFile(Path) |
+| DeleteDocNoFile | 刪除特定文件代號下所有影像 | 整批文件(DocNo)的物理刪除與序號重整 | DeleteFilesByPattern(Pattern) |
+| DeleteShowFile | 刪除 UI 顯示中的影像清單 | 根據介面選取狀態進行批次物理刪除 | DeleteFileList(List<Path>) |
+| RenameFile / MoveFile | 檔案搬移或更名 | 用於「分案」、「移動頁數」或「變更歸類」 | MoveFile(Src, Dest) |
+| CopyFile | 複製實體檔案 | 影像搬移至上傳區或引用舊案件影像 | CopyFile(Src, Dest) |
+
+### **4. 資料紀錄與序列化 (Metadata IO)**
+
+| **方法名稱** | **作用** | **應用場景** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| DeleteCustomDocDir | 移除自訂文件定義 | 從 CustomDocNo.ini 中移除特定自訂文件的節點 | Storage.IniDeleteSection(Section) |
+
+### **5. 網路傳輸 IO 方法 (Network Retrieval - dnFile_Get)**
+
+專案中使用 `dnFile_Get` 從伺服器端同步必要的環境檔案或規則定義。
+
+| **抓取對象 (目標路徑)** | **遠端請求 Action** | **用途說明** | |
+| --- | --- | --- | --- |
+| **CheckXmlPath + filename** | `GetCheckXml` | **下載 OMR 檢核定義檔**。同步伺服器端最新的 XML 座標規則,用於自動判斷影像區域。 | https |
+| **SamplePath + filename** | `GetSampleImg` | **下載範本影像**。用於在 UI 介面上提供給操作員對照的標準範例圖檔。 | https |
+| **SitePath + filename** | `GetSiteImg` | **下載定位定義圖**。下載與登打、校對位置相關的輔助影像。 | https |
+| **LngPath + 'Language.ini'** | `GetLanguage` | **同步多國語言檔**。確保用戶端介面文字(繁體、英文、越南語等)與伺服器同步。 | https |
+
+## **參、 資料紀錄與序列化 (Metadata IO)**
+
+專案中使用了大量的 .dat 與 .ini 檔案來記錄目錄內的結構資訊與使用者偏好。
+
+### **1. .dat 檔案 (結構紀錄)**
+
+| **檔案名稱** | **組合路徑邏輯 (Path Logic)** | **內容與用途** |
+| --- | --- | --- |
+| **Context.dat** | ImageSavePath + CaseID + '\' + DocDir + '\Context.dat' | **影像清單**。紀錄該資料夾內所有影像檔名的正確順序。 |
+| **DocDir.dat** | ImageSavePath + CaseID + '\Upload\DocDir.dat' | **目錄對應表**。紀錄 Upload 下每個檔名所屬的原始 DocDir |
+| **CaseDocNo.dat** | ImageSavePath + CaseID + '\CaseDocNo.dat' | **文件目錄索引**。紀錄案件內已建立的實體資料夾名稱。 |
+| **CaseDocNo_Copies.dat** | ImageSavePath + CaseID + '\CaseDocNo_Copies.dat' | **份數紀錄**。對應 CaseDocNo.dat 中的資料夾分別有多少份。 |
+| **CaseIndex.dat** | ImageSavePath + CaseID + '\CaseIndex.dat' | **案件屬性**。如是否為「授信卷」(Case_loandoc)。 |
+| **EditedDocDir.dat** | ImageSavePath + CaseID + '\EditedDocDir.dat' | **異動清單**。紀錄當次操作中被修改過的文件目錄。 |
+| **Scan_Memo.dat** | DisplayPath + 'Scan_Memo.dat' | **使用者註記**。紀錄操作員手動輸入的備註內容。 |
+| **CaseList.dat** | ImageSavePath + 'CaseList.dat' | **案件總表**。紀錄目前本機快取中存在的所有 CaseID。 |
+
+### **2. .ini 檔案 (設定與偏好)**
+
+| **檔案名稱** | **路徑邏輯** | **回寫 (Write-back)** | **內容與用途** | 寫入關聯 |
+| --- | --- | --- | --- | --- |
+| **Scan.ini** | ScaniniPath + 'Scan.ini' | **是 (頻繁)** | **掃描器硬體設定**。儲存最後一次選取的 DPI、雙面、色彩模式、亮度、對比等參數。 | |
+| **CustomDocNo.ini** | ScaniniPath + 'CustomDocNo.ini' | **是 (中等)** | **自訂文件代號**。儲存操作員定義的文件分類名稱與內部 ID 映射。 | DeleteCustomDocDir |
+| **CB_IMGPSScan.ini** | LngPath + 'CB_IMGPSScan.ini' | **是 (低頻)** | **環境配置**。儲存伺服器 IP、Port、自動更新版本資訊等全域參數。 | |
+| **Language.ini** | LngPath + 'Language.ini' | **否 (唯讀同步)** | **多國語言包**。僅透過 `dnFile_Get` 從伺服器抓取更新,OCX 不自行修改。 | |
+
+## **肆、 串流與讀寫操作 (Stream & File I/O)**
+
+源碼中頻繁使用 .LoadFromFile 與 .SaveToFile 來實現資料的持久化。
+
+### **1. 使用 TStringList 讀寫 .dat 結構**
+
+| **操作對象** | **讀取場景 (Load)** | **寫入場景 (Save)** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| **結構清單 (.dat)** | LoadImgFile 載入以重建樹狀結構 | PageEnd 掃描完成或結構增刪後即時存檔 | ReadTextFile(Path) / WriteTextFile(Path, Content) |
+| **備註文件 (Memo)** | 進入備註編輯器時載入舊有內容 | WNoteBtnClick 完成編輯後儲存內容 | ReadTextFile(Path) / WriteTextFile(Path, Content) |
+| **上傳包定義** | N/A | CreateFormID_FormName 產生上傳包所需的定義檔 | WriteTextFile(Path, Content) |
+| | | | |
+
+### **2. 使用 TImageScrollBox / TDibGraphic 讀寫影像**
+
+| **操作對象** | **讀取場景 (Load)** | **寫入場景 (Save)** | **建議抽象 IO 介面** |
+| --- | --- | --- | --- |
+| **掃描影像原始檔** | view_image_... 載入顯示於預覽窗 | OnAcquire 將記憶體影像 (Dib) 持久化至磁碟 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+| **影像處理覆蓋** | ImageReSize_FormID 讀取進行定位縮放 | 處理完成後覆蓋原始影像檔 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+| **旋轉/後製處理** | 點擊旋轉按鈕後從磁碟重新讀取 | 旋轉完成後保存更新內容回實體檔案 | ReadBinaryFile(Path) / WriteBinaryFile(Path, Blob) |
+
+## **伍、 檔案路徑構造邏輯示例**
+
+程式中典型的路徑構造方式如下(以 PageEnd 為例):
+
+// 1. 基礎路徑
+
+ScanPath := ImageSavePath + ScanCaseno + '\';
+
+// 2. 進入特定文件目錄 (DocDir)
+
+ScanPath := ScanPath + ScanDocdir + '\';
+
+// 3. 確保實體目錄存在
+
+Str2Dir(ScanPath);
+
+// 4. 構造最終影像路徑
+
+PEFileName := ScanPath + Add_Zoo(PageCount, 3) + '_' + FormID + ext;
+
+## **陸、 IO 方法具體實作邏輯細部說明 (Detailed Implementation Logic)**
+
+本節針對 CB_IMGPSScanImp.pas 內部如何透過 Windows API 實作這些 IO 操作進行細部解說。
+
+### **1. Str2Dir(Path: string) 的運作機制**
+
+這個方法的主要作用是 **「路徑標準化與實體資料夾建立」**。
+
+- **字串處理**:它會先檢查傳入的 Path 字串最後一個字元是否為 \。如果不是,會自動補上。
+- **建立資料夾**:**是的,它會在內部建立資料夾**。它會呼叫 Delphi 的 ForceDirectories(Path) 函式。
+- **ForceDirectories 的特性**:與一般的 CreateDir 不同,ForceDirectories 會「遞迴」建立路徑中所有不存在的父目錄(例如若路徑為 C:\A\B\C,即使 A 和 B 都不存在,它也會一併建立)。
+
+### **2. _DelTree(DirName: string) 的遞迴邏輯**
+
+由於 Delphi 早期版本沒有提供單一函式來刪除包含檔案的資料夾,此方法透過 Windows 的搜尋機制實現:
+
+- **遍歷搜尋**:使用 FindFirst 和 FindNext 找出資料夾內的所有物件。
+- **檔案處理**:若搜尋到的是一般檔案,直接呼叫 DeleteFile。
+- **遞迴處理**:若搜尋到的是子資料夾,則「自己呼叫自己」 (_DelTree) 先清空該子資料夾。
+- **物理移除**:當資料夾內的所有內容都清空後,呼叫 RemoveDir 將空的資料夾從磁碟移除。
+
+### **3. FindFirst 與 FindNext 的搜尋與疊代邏輯**
+
+這兩個方法是 Delphi 處理「集合式 IO 操作」(如掃描目錄、批次刪除)的基礎,通常搭配 TSearchRec 結構使用。
+
+- **FindFirst(Path, Attr, SearchRec)**:
+- **動作**:啟動搜尋任務,將找到的第一個檔案資訊填入 SearchRec。
+- **應用例**:在 PM104Click (匯入影像) 時,程式會先執行 FindFirst(FName, faAnyfile, FileRec) 來確認使用者選取的實體檔案是否存在,並藉由 FileRec.Size 取得位元組大小,用以判斷是否超過系統設定的匯入限制(例如 5MB)。
+- **FindNext(SearchRec)**:
+- **動作**:繼續尋找下一個符合條件的檔案。
+- **疊代模式**:通常包裹在 repeat ... until FindNext(SR) <> 0 迴圈中。
+- **應用例**:在 _DelTree 實作中,程式利用此疊代邏輯將資料夾內「所有的」子目錄與檔案清空,直到 FindNext 回傳非零值(代表搜尋結束)。
+- **FindClose(SearchRec)**:
+- **重要性**:釋放搜尋控制代碼(Handle)。若未呼叫,頻繁搜尋會導致系統資源洩漏。
+
+### **4. GetNoNameCase(Path: string) 的搜尋邏輯**
+
+這是一個典型的 **「可用名稱查表」** 實作:
+
+- **迴圈範圍**:從 1 迭代到 9999。
+- **格式組合**:使用 Add_Zoo 函式將數字轉為四位數(如 0001),並加上前綴字「未配號」。
+- **磁碟檢查**:呼叫 DirectoryExists 檢查 Path + '未配號000x'。
+- **結果回傳**:第一個回傳 False(代表該資料夾尚不存在)的名稱即為結果,程式會立即跳出迴圈並選定此名稱。
+
+### **5. ReSortFileName(Path: string) 的連續性維護**
+
+為了保證 UI 上顯示的頁碼順序與磁碟檔名一致,此方法採用「先暫存、後改名」的策略:
+
+- **防止衝突**:先將目錄內所有符合格式的影像更名為帶有臨時前綴(如 @)的檔名。
+- **按序更名**:讀取 Context.dat 內的清單,依照目前的順序,將檔案逐一更名為 001_..., 002_... 等格式。
+- **同步索引**:最後將更名後的結果重新寫入 Context.dat。
+
+### **6. GetLocalAppDir(Handle: HWND) 的權限繞過**
+
+這是一個系統級別的 IO 位置定位方法:
+
+- **API 呼叫**:呼叫 SHGetSpecialFolderPath (Windows Shell API)。
+- **定位 CSIDL_LOCAL_APPDATA**:指向 C:\Users\使用者名稱\AppData\Local\。
+- **必要性**:這能解決 OCX 程式被安裝在 Program Files 下時,因為 UAC 權限無法在安裝目錄寫入 Log 或語言檔的問題。
+
+### **🎯 移植至 Web 平台的建議**
+
+當您將這些邏輯移植到 Web 時:
+
+- Str2Dir 應對應到 **IndexedDB** 的 Object Store 建立或 **File System Access API** 的 getDirectoryHandle(搭配 create: true)。
+- FindFirst / FindNext 在 Web 端應對應到 Directory Handle 的 entries() 異步疊代器。
+- .dat 序列化文件在 Web 端建議直接轉為 **JSON** 格式存儲於瀏覽器的 localStorage 或 IndexedDB 中。
+
+## **柒、 設定檔回寫邏輯 (Write-back Logic)**
+
+本節說明專案中哪些 .ini 檔案會由 OCX 主動更新資料及其觸發時機。
+
+| **檔案名稱** | **回寫內容 (Content)** | **觸發時機 (Trigger)** |
+| --- | --- | --- |
+| **Scan.ini** | DPI、Duplex、亮度、對比、影像模式 | 掃描前設定變更或啟動掃描時(SaveScanPara)。 |
+| **CustomDocNo.ini** | 自訂文件名稱與 ID 映射 | 操作員新增自訂分類或呼叫 `DeleteCustomDocDir` 時。 |
+| **CB_IMGPSScan.ini** | 版本號、伺服器 IP/Port | 自動更新完成後更新版號,或手動修改伺服器設定時。 |
+
+## **捌、 注意事項**
+
+- **硬編碼路徑**:ActiveFormCreate 中存在寫死的 C:\Temp\IMGPSScan,適合作為最終保險。
+- **權限問題**:作為 ActiveX,這些 IO 操作強烈依賴瀏覽器的「安全站台設定」或 IE 的「保護模式」。使用 GetLocalAppDir 是現代化重構中解決 UAC 權限問題的重要手段。
+
+---
+
+# **TCB_IMGPSScanX OCX 通訊介面與溝通機制分析**
+
+本表條列了 Delphi 宿主環境(ActiveX[ocx]) 與 TCB_IMGPSScanX 元件之間主要的溝通管道、對應方法及其在系統架構中的作用。
+
+## **壹、 指令與資料交換介面表**
+
+| **通訊方法 (Method)** | **通訊方向** | **溝通內容 (Data Payload)** | **具體作用與目的** |
+| --- | --- | --- | --- |
+| **SetSQLData** | **宿主 -> OCX** | 以 ` | 或,` 分隔的長字串(如:IP, CaseID, DPI) |
+| **GetSQLData** | **宿主 <-> OCX** | 指定 Key (如 'PARA_NO') 取得對應 Value | **資料查詢通道**。宿主可詢問 OCX 目前快取清單中的特定數值,用於介面同步或邏輯判斷。 |
+| **GetSetInf1 ~ 7** | **宿主 <- OCX** | 單一字串值 (如 CaseID, 總張數, 成功標記 'Y') | **狀態出口 (Outlets)**。提供標準化的 7 個出口,讓 JavaScript 或宿主 App 輪詢(Polling)目前的執行結果或掃描統計。 |
+| **StatrTwainScan** | **宿主 -> OCX** | 無參數 (觸發動作) | **硬體啟動指令**。宿主程式按下「開始掃描」按鈕後呼叫此方法,通知 OCX 喚起 TWAIN 驅動程式。 |
+| **GetCurrentVersionNo** | **宿主 <- OCX** | 版本字串 (如 '1.0.3.5') | **版本識別**。宿主程式載入 OCX 後第一步通常會呼叫此處,用以比對伺服器版本並決定是否強制更新。 |
+| **upFile** | **宿主 -> OCX** | 無或部分參數 (觸發網路 IO) | **輸出指令**。通知 OCX 將本機暫存區的檔案(如 ZIP 包)依照先前設定好的路徑與權限上傳至伺服器。 |
+| **dnFile_Get** | **宿主 -> OCX** | 遠端 Action 關鍵字與本地檔名 | **同步指令**。通知 OCX 向伺服器抓取特定資源(如 XML 規則或語言檔)並存放到指定 IO 路徑。 |
+| **ActiveFormCreate** | **系統 -> OCX** | 視窗建立事件 | **環境初始化**。當宿主程式實體化 OCX 時,自動觸發此處執行 GetDefScanIni,確保掃描環境就緒。 |
+| **Property CaseID** | **宿主 <-> OCX** | WideString | **屬性直連**。透過 COM 屬性機制直接設定或讀取案件編號。 |
+| **Property ScreenSnap** | **宿主 -> OCX** | Boolean | **功能切換**。控制 OCX 是否要在特定時機執行螢幕截圖稽核。 |
+
+## **貳、 溝通機制細部說明**
+
+### **1. 參數化配置 (Config-by-String)**
+
+本專案大量使用 SetSQLData 這種「一條字串走天下」的設計,這在早期 ActiveX 開發中非常流行,優點是規避了 COM 介面頻繁修改 _TLB.pas 的麻煩。您在轉換 TypeScript UI 時,可以將其封裝為一個 JSON 物件,最後再組合成字串傳給這個方法。
+
+### **2. 狀態回饋 (The Inf1~7 Pattern)**
+
+由於 ActiveX 事件 (Events) 的回傳有時在網頁端不夠穩定,開發者選擇了 GetSetInf 系列。宿主程式通常會在執行完某個長耗時動作(如 upFile)後,連續呼叫 GetSetInf3 (成功標記) 與 GetSetInf6 (錯誤訊息) 來決定下一步 UI 流程。
+
+### **3. 雙向同步 (Bidirectional Sync)**
+
+- **同步設定**:宿主透過 GetDefScanIni 觸發,OCX 內部完成硬體設定。
+- **同步資料**:宿主透過 dnFile_Get 觸發,OCX 完成本機與伺服器的檔案 IO 同步。
+
+# **參、描服務抽象層實作**
+
+採用 **「抽象介面層 (Abstraction Layer)」** 配合 **「適配器模式 (Adapter Pattern)」**,處理遺留系統(Legacy System)過渡到現代化架構
+
+```tsx
+/**
+ * 掃描服務資料模型定義
+ * 將原本 OCX 雜亂的字串溝通 (SetSQLData) 結構化
+ */
+export interface ScanConfig {
+ serverIp: string;
+ caseId: string;
+ dpi: number;
+ isColor: boolean;
+ isDuplex: boolean;
+ // ... 其他來自 GetDefScanIni 的參數
+}
+
+export interface ScanStatus {
+ caseId: string;
+ totalPageCount: number;
+ isUploadSuccess: boolean;
+ lastBarcode: string;
+ errorMessage: string;
+}
+
+/**
+ * 掃描服務抽象介面 (IScanService)
+ * UI 層僅與此介面溝通,不直接操作底層實作
+ */
+export interface IScanService {
+ initialize(config: ScanConfig): Promise<void>;
+ startScan(): Promise<boolean>;
+ uploadFiles(): Promise<boolean>;
+ getStatus(): Promise<ScanStatus>;
+ getVersion(): Promise<string>;
+ downloadResource(action: string, fileName: string): Promise<void>;
+}
+
+/**
+ * 實作 A: ActiveX 適配器 (Legacy Adapter)
+ * 用於目前環境:UI (TS) -> Delphi Browser -> ActiveX (OCX)
+ */
+export class ActiveXScanAdapter implements IScanService {
+ private ocx: any;
+
+ constructor() {
+ // 透過 window.external 或 Delphi Bridge 取得 OCX 實例
+ this.ocx = (window as any).OCX_INSTANCE;
+ }
+
+ async initialize(config: ScanConfig): Promise<void> {
+ // 將 JSON 轉回 OCX 慣用的管道分隔字串 (SetSQLData 邏輯)
+ const sqlDataStr = `${config.serverIp}|${config.caseId}|${config.dpi}|${config.isColor ? 'C' : 'G'}`;
+ this.ocx.SetSQLData(sqlDataStr);
+ }
+
+ async startScan(): Promise<boolean> {
+ this.ocx.StatrTwainScan();
+ return true; // 實際狀態需透過 GetSetInf 輪詢
+ }
+
+ async getStatus(): Promise<ScanStatus> {
+ return {
+ caseId: this.ocx.GetSetInf1(),
+ totalPageCount: parseInt(this.ocx.GetSetInf2()),
+ isUploadSuccess: this.ocx.GetSetInf3() === 'Y',
+ lastBarcode: this.ocx.GetSetInf5(),
+ errorMessage: this.ocx.GetSetInf6()
+ };
+ }
+
+ async uploadFiles(): Promise<boolean> {
+ this.ocx.upFile();
+ return true;
+ }
+
+ async getVersion(): Promise<string> {
+ return this.ocx.GetCurrentVersionNo();
+ }
+
+ async downloadResource(action: string, fileName: string): Promise<void> {
+ this.ocx.dnFile_Get(action, fileName);
+ }
+}
+
+/**
+ * 實作 B: Backend Server 適配器 (Future Adapter)
+ * 用於未來環境:UI (TS) -> REST API / WebSocket -> Rust/Go Backend
+ */
+export class BackendServerAdapter implements IScanService {
+ private apiUrl = "http://localhost:8080/api/scanner";
+
+ async initialize(config: ScanConfig): Promise<void> {
+ await fetch(`${this.apiUrl}/config`, {
+ method: 'POST',
+ body: JSON.stringify(config)
+ });
+ }
+
+ async startScan(): Promise<boolean> {
+ const res = await fetch(`${this.apiUrl}/scan`, { method: 'POST' });
+ return res.ok;
+ }
+
+ async getStatus(): Promise<ScanStatus> {
+ const res = await fetch(`${this.apiUrl}/status`);
+ return await res.json();
+ }
+
+ async uploadFiles(): Promise<boolean> {
+ const res = await fetch(`${this.apiUrl}/upload`, { method: 'POST' });
+ return res.ok;
+ }
+
+ async getVersion(): Promise<string> {
+ const res = await fetch(`${this.apiUrl}/version`);
+ const data = await res.json();
+ return data.version;
+ }
+
+ async downloadResource(action: string, fileName: string): Promise<void> {
+ // 未來可能直接由後端處理,前端僅發送同步指令
+ await fetch(`${this.apiUrl}/sync?action=${action}&file=${fileName}`);
+ }
+}
+
+/**
+ * 服務工廠 (Scanner Factory)
+ * 根據環境自動切換實作
+ */
+export class ScannerFactory {
+ static getService(): IScanService {
+ if ((window as any).OCX_INSTANCE) {
+ console.log("偵測到 ActiveX 環境,啟用 ActiveX 適配器");
+ return new ActiveXScanAdapter();
+ } else {
+ console.log("現代瀏覽器環境,啟用後端 API 適配器");
+ return new BackendServerAdapter();
+ }
+ }
+}
+```
+
+### **1. 介面標準化(JSON 化)**
+
+原先 OCX 使用 SetSQLData 的「長字串」溝通是非常脆弱的(一項參數順序錯了就全毀)。在 TypeScript 抽象層中,請務必將其轉換為 **強型別的 JSON 物件**(如 ScanConfig 介面)。這樣你的 UI 邏輯在處理設定時會非常直覺。
+
+### **2. 非同步處理(Promise/Async)**
+
+ActiveX 的方法通常是同步阻塞的,而後端 API 是非同步的。
+
+- **建議**:在抽象介面(IScanService)中,所有方法都回傳 Promise。
+- **原因**:這樣當你未來切換到後端伺服器(fetch API)時,UI 的調用邏輯(await service.startScan())不需要做任何修改。
+
+### **3. 實作「心跳」或「狀態輪詢」**
+
+原本 GetSetInf1~7 主要是靠宿主程式主動去「問」OCX。
+
+- **抽象層建議**:在 IScanService 中實作一個 subscribeStatus(callback) 的觀察者模式。
+- **ActiveX 模式下**:在適配器內部啟動一個 setInterval 去輪詢 GetSetInf。
+- **未來後端模式下**:適配器改用 **WebSocket** 接收後端主動推播的掃描事件。
+- **UI 層感受**:UI 只需要處理 onStatusUpdate 事件,根本不用管底層是用輪詢還是 WebSocket。
+
+### **4. 資源路徑的轉義(The Bridge Proxy)**
+
+這是我之前提到的關鍵:由於 iframe 裡的 TypeScript 無法存取 C:\Temp,但 ActiveX 依舊會把檔案掃到那裡。
+
+- **策略**:你的 Delphi Browser 需要實作一個簡單的本地 Proxy。
+- **實作**:當 TypeScript 需要顯示圖檔時,它請求 http://local.bridge/view/001.tif,Delphi Browser 攔截此請求並從實體路徑讀取檔案回傳。
+- **好處**:未來改為 Backend Server 時,Server 也可以提供同樣的 URL 格式,UI 完全無縫接軌。
+
+## **肆、 Delphi 與 JavaScript 通訊橋樑 (Bridge) 實作說明**
+
+當您在 Delphi 宿主程式中使用內嵌瀏覽器時,JavaScript 取得 `OCX_INSTANCE` 的方式取決於底層的瀏覽器引擎:
+
+### **1. 舊版 IE 核心 (TWebBrowser / window.external)**
+
+這是最傳統的方式,Delphi 會透過實作 `IDocHostUIHandler` 介面,將一個自訂的 `IDispatch` 物件掛載到 `window.external` 上。
+
+- **Delphi 端**:將 `TCB_IMGPSScanX` 實例或其包裝類別指派給瀏覽器的 `External` 屬性。
+- **JS 端**:直接使用 `window.external.StatrTwainScan()` 呼叫。
+
+### **2. 新版 Edge 核心 (TEdgeBrowser / WebView2 Host Objects)**
+
+這是現代化的做法。Delphi 透過 WebView2 的 API 將物件直接「注入」到 JS 的命名空間中。
+
+- **Delphi 端執行**:
+
+ ```pascal
+ // 將 OCX 物件以 'OCX_INSTANCE' 名稱注入
+ EdgeBrowser.AddHostObjectToScript('OCX_INSTANCE', MyOcxWrapperObject);
+ ```
+
+- **JS 端取得**: WebView2 會將物件放置在 `window.chrome.webview.hostObjects` 底下。
+
+ ```jsx
+ const ocx = window.chrome.webview.hostObjects.OCX_INSTANCE;
+ ```
+
+
+### **3. 為什麼需要 Wrapper (包裝類別)?**
+
+通常我們**不建議**直接將 `TCB_IMGPSScanX` 注入,原因如下:
+
+1. **安全性**:直接暴露 COM 元件可能會有安全漏洞。
+2. **相容性**:OCX 的某些方法回傳型別(如 Delphi 的自訂 Enum)JavaScript 無法識別。
+3. **執行緒優化**:Delphi 可以在 Wrapper 中使用 `TThread.Queue` 確保掃描指令在正確的執行緒執行,避免瀏覽器 UI 凍結。
+
+### **4. 溝通路徑總結**
+
+1. **Delphi 宿主程式** 啟動並實體化 **OCX 控制項**。
+2. **Delphi 宿主程式** 建立 **Browser 物件** 並載入 **TypeScript UI (HTML)**。
+3. **Delphi 宿主程式** 呼叫瀏覽器 API(如 `AddHostObjectToScript`),將 OCX 的操作介面「注入」到該網頁的 `window` 物件中。
+4. **TypeScript** 透過抽象層 (Adapter) 取得該物件,實現「網頁點按鈕,掃描機開動」的效果。
+
+---
+
+
+# Transport 相關套件分析
+
+---
+
+# Image Processor 相關套件分析
diff --git a/separate/scanImp/CB_IMGPSScanImp_Data.pas b/separate/scanImp/CB_IMGPSScanImp_Data.pas
new file mode 100644
index 0000000..7a7a89a
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Data.pas
@@ -0,0 +1,5178 @@
+function TCB_IMGPSScanX.Get_HelpFile: WideString;
+begin
+ Result := WideString(HelpFile);
+end;
+
+procedure TCB_IMGPSScanX.Set_HelpFile(const Value: WideString);
+begin
+ HelpFile := string(Value);
+end;
+
+function TCB_IMGPSScanX.DocNoIsExistImg(DocNopath:String):boolean;
+var
+ i:integer;
+ ST:TStringList;
+begin
+ Result:=False;
+ ST:=TStringList.Create;
+ if FileExists(DocNopath+'\Context.dat') then /////20190319 Hong 當有空的Docno目錄時會掛掉,增加這行
+ ST.loadFromfile(DocNopath+'\Context.dat');
+ for I := 0 to ST.Count - 1 do
+ begin
+ if ISExistImg(DocNopath+ST.Strings[i]) then
+ begin
+
+ Result:=False;
+ Exit;
+ Break;
+ end;
+ end;
+ Result:=True;
+
+
+end;
+
+procedure TCB_IMGPSScanX.HTTPSClientCertificateValidate(Sender: TObject;
+ X509Certificate: TElX509Certificate; var Validate: Boolean);
+begin
+ Validate := True;
+end;
+
+procedure TCB_IMGPSScanX.HTTPSClientRedirection(Sender: TObject;
+ const OldURL: string; var NewURL: string; var AllowRedirection: Boolean);
+begin
+ AllowRedirection := True;
+end;
+
+Function TCB_IMGPSScanX.GetServerDate : Boolean;
+begin
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/servertimeforocx','',FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ ServerDate := memo1.Lines.Strings[1];
+ ServerTime := Copy(ServerDate,9,6);
+ ServerDate := Copy(ServerDate,1,8);
+ Balance := GetBalance(ServerTime); //Server 跟Local的時間差
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.GetSetInf1 : Boolean; //取系統設定資訊Mode1 DOC_INF
+Var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT %s FROM DOC_INF WHERE WORK_NO = '%s' ORDER BY DOC_TYPE, DOC_NO, DOC_VERSION"
+
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+
+ ColumeStr := 'WORK_NO,DOC_NO,DOC_U_DESC,DOC_TYPE,DOC_VERSION,FORM_PAGES,START_DATE,STOP_DATE,IS_DOC_DIV,IS_IN_WH';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=1&col='+Doc_Inf_Colume+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=1&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,Doc_Inf_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf2 : Boolean; //取系統設定資訊Mode2 DM_FORM_INF
+var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT %s FROM DM_FORM_INF
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ColumeStr := 'WORK_NO,MAIN_FORM_ID,DOC_VERSION,DEPE_FORM_ID,MUTEX_FORM_ID';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=2&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=2&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,DM_FORM_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf3 : Boolean; //取系統設定資訊mode3 FORM_INF
+var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT distinct %s FROM FORM_INF T1 LEFT JOIN DOC_INF T2 ON T2.DOC_NO = T1.DOC_NO AND T1.DOC_VERSION = T2.DOC_VERSION AND T1.WORK_NO = T2.WORK_NO WHERE T2.IS_USE = 'Y' AND T2.WORK_NO = %s
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ //ColumeStr := 'T1.WORK_NO,T1.FORM_ID,T1.DOC_KIND,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.MERGE_IMAGE,T1.CC_FORM_ID,T1.CC_MERGE_FORMID,T2.DOC_TYPE'; {T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
+ ColumeStr := 'T1.WORK_NO,T1.FORM_ID,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.IS_PRINT,T2.DOC_TYPE'; {T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=3&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=3&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,FORM_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf4 : Boolean; //取系統設定資訊mode4 CHECK_RULE_INF
+var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT %s FROM CHECK_RULE_INF WHERE CHECK_TYPE = 'S'
+
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ColumeStr := 'WORK_NO,CHECK_NO,CHECK_RULE_DESC,MESG_SHOW_TYPE,MESG_DISP_TYPE,CHECK_MESG,SCAN_MODE';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=4&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=4&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,CHECK_RULE_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+ CheckRule2OMRErrInfo;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf5 : Boolean; //取系統設定資訊mode5 MEMO_INF
+ var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT %s FROM MEMO_INF T1 LEFT JOIN MEMO_TYPE_INF T2 ON T2.MEMO_TYPE_NO = T1.MEMO_TYPE WHERE T1.MEMO_SOURCE = '01'
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ColumeStr := 'T1.WORK_NO,T1.MEMO_TYPE,T1.MEMO_CONTENT,T2.MEMO_TYPE_NAME';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=5&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,MEMO_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf6 : Boolean; //取系統設定資訊mode5 WORK_INF
+var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT %s FROM WORK_INF
+
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ColumeStr := 'WORK_NO,PARA_NO,PARA_CONTENT';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=6&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,WORK_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSetInf7 : Boolean; //取系統設定資訊mode5 LASTEST_FORM_INF
+var
+ ColumeStr : String;
+ S : TStringlist;
+ EnCodeDateTime : String;
+begin
+ //SELECT FORM_ID,DOC_NO,DOC_VERSION FROM FORM_INF WHERE (DOC_NO,DOC_VERSION) in (SELECT DOC_NO, MAX(DOC_VERSION) FROM FORM_INF GROUP BY DOC_NO) ORDER BY DOC_NO
+
+ Result := False; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ColumeStr := 'FORM_ID,DOC_NO';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=7&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ S := TStringlist.Create;
+ S.Text := Memo1.Lines.Text;
+ SetSQLData(ColumeStr,S,LASTEST_FORM_INF_List);
+ S.Free;
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
+var
+ i : Integer;
+begin
+ for i := 1 to Doc_Inf_List.Count - 1 do
+ begin
+
+ if GetSQLData(Doc_Inf_List,'IS_IN_WH',i) = 'Y' then
+ IN_WH_DocNoList.Add(GetSQLData(Doc_Inf_List,'DOC_NO',i));
+ end;
+ {Showmessage(IN_WH_DocNoList.Text);
+ StringtoFile(IN_WH_DocNoList.Text,'D:\121.txt');}
+end;
+
+Function TCB_IMGPSScanX.DeleteDocNoFile(Path,DocNo:String):Boolean; //刪除指定DocNo文件
+var
+ i: Integer;
+ FName : String;
+begin
+ Result := False;
+ for i := ContextList.Count - 1 downto 0 do
+ begin
+ FName := ContextList.Strings[i];
+ If DocNo = FormCode2DocNo(FileName2FormCode(FName)) then
+ begin
+ DeleteFile(Path+FName);
+ ContextList.Delete(i);
+ Context_DocnoList.Delete(i);
+ Result := True; //有刪到指定文件
+ end;
+ end;
+ ContextList.SaveToFile(Path+'Context.dat');
+ Context_DocnoList.SaveToFile(Path+'Context_DocNo.dat');
+ ReSortFileName(Path);
+ ContextList.LoadFromFile(Path+'Context.dat');
+ Context_DocnoList.LoadFromFile(Path+'Context_DocNo.dat');
+ if FileExists(Path+'CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(Path+'CustomDocNo.dat');
+end;
+
+Procedure TCB_IMGPSScanX.DeleteShowFile(Path:String); //刪除顯示中的影像
+var
+ i : Integer;
+ DelFile : String;
+begin
+ for i := 0 to NowShowFileList.Count - 1 do
+ begin
+ DelFile := NowShowFileList.Strings[i];
+ DeleteFile(Path+DelFile);
+ SetContextList('D',-1,NowCaseno,NowDocNo,DelFile);
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.GetDataDocNoPage(MainDocNo,MainVersion:String):Integer; //取記錄的文件_版本頁數
+var
+ P : String;
+begin
+ Result := 0;
+ If FindSQLData(Doc_Inf_List,'FORM_PAGES','DOC_NO,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) Then
+ begin
+ P := GetFindResult('FORM_PAGES');
+ if P <> '' then
+ Result := strtoint(P)
+ else
+ Result := 0;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckCaseDocNoPage(CaseID,DocNo,Version:String;Pages:Integer):Integer; //取案件裡的文件_版本頁數
+var
+ i,n,Count : integer;
+ S, S2 : TStringlist;
+ FormCode,iPage : String;
+ docInt,tempInt:integer;
+ v,v2:integer;
+begin
+ Count := 0;
+ docInt:=0;
+ tempInt:=0;
+ S := TStringlist.Create;
+ S2 := TStringlist.Create;
+//ShowMessage('page='+IntToStr(Pages));
+ try
+ S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
+ S2.LoadFromFile(ImageSavePath+CaseID+'\upload\DocDir.dat'); //2017 1220 改成只承認第一份的
+
+ for I := 1 to pages do //從0到pages-1 改成 1到pages 20170316 這樣可以修改檢核的頁數問題
+ begin
+ iPage := Add_Zoo(i,2);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[n]) then
+ begin
+ Continue;
+ end;
+ end;
+
+ if (Length(S2.Strings[n])>8) and (Pos(DocNo,S2.Strings[n])<>0) then //2017 1220 改成只承認第一份的
+ begin
+//LogFile1.LogToFile(logTimeString+'有進'+docno+','+S2.Strings[n]+IntToStr(Pos(DocNo,S2.Strings[n])));
+ v:=Pos('(',S2.Strings[n]);
+ v2:=Pos(')',S2.Strings[n]);
+ tempInt:=StrToInt(Copy(S2.Strings[n],v+1,v2-v-1));
+
+ if docInt=0 then
+ begin
+ docInt:=tempInt;
+ end;
+ if docInt<>tempInt then
+ begin
+//LogFile1.LogToFile(logTimeString+'docInt='+IntToStr(docInt)+',tempInt='+IntToStr(tempInt));
+ Result := Count;
+ Break;
+ end;
+ end;
+
+ FormCode := FileName2FormCode(S.Strings[n]);
+//LogFile1.LogToFile(logTimeString+'S.Strings[n]='+S.Strings[n]);
+//Showmessage('1:'+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
+//LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
+LogFile1.LogToFile(logTimeString+'CheckCaseDocNoPage caseno='+CaseID+','+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
+//ShowMessage(DocNo+','+IntToStr(docInt)+','+IntToStr(tempInt));
+//LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
+ if (version = FormCode2Version(FormCode)) and (DocNo = FormCode2DocNo(FormCode)) and (ipage = FormCode2Page(FormCode)) then
+ begin
+LogFile1.LogToFile(logTimeString+'CheckCaseDocNoPage caseno='+CaseID+','+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
+//Showmessage(version+','+DocNo+',iPage='+iPage);
+//Showmessage(inttostr(Count+1));
+ Inc(Count);
+ Break; //找到了...離開
+ end;
+ end;
+ end;
+ finally
+ S.Free;
+ S2.free;
+ end;
+ Result := Count;
+end;
+
+Function TCB_IMGPSScanX.TransCaseID(Path,CaseID:String;MainCase:Boolean):Boolean; //傳送案件
+Var
+ i,n,v: Integer;
+ ZipFileList : TStringlist;
+ UpFormID:String;
+ pages : Integer;
+ TransName : String;
+ MaskPath : String;
+ HaveMask : Boolean;
+ S : String;
+ SendData:String;
+ Doc_Data,Doc_Data1 : String;
+ In_Doc1,In_Doc2 : String;
+ AttachYN : String; //是否有附件 Y:有 N:沒有
+
+ ST1,ST2,ST3:TStringList;
+ str1,str2:String;
+ must_formidStr :string;
+ last_add_formidstr :string;
+ ScanListStr:String;
+ casepath:String;
+ filesizeInt:integer;
+ case_page:string;
+ Fname:String;
+ FileRec:TSearchrec;
+begin
+ Result := True;
+ TransName := CaseID;
+ MaskPath := Path+'MaskImg\';
+ if fileExists(Path+'Context.dat') then
+ begin
+ ContextList.LoadFromFile(Path+'Context.dat');
+ Context_DocnoList.LoadFromFile(Path+'Context_DocNo.dat');
+ end;
+
+ if FileExists(Path+'CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(Path+'CustomDocNo.dat');
+
+ Pages := ContextList.Count;
+ case_page:=IntToStr(pages);
+ if (FMode = 'NSCAN') or (FMode = 'ESCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') or (FMode = 'RSCAN') then
+ begin
+ //Showmessage('1');
+ UpformID := GetCaseFormID(Path);
+ {if UpformID = '' then //20131213 yuu說不管主form
+ begin
+ Showmessage(_msg('取不到主FormID!!'));
+ Result := False;
+ DataLoading(False,False);
+ Exit;
+ end;}
+ end;
+
+ CaseResort2Scanlist(Path); //檔名照設定排序產生scanlist.dat
+ //CaseResort(Path); //檔名照設定排序
+ CreateFormID_FormName(Path,CaseID); //產生FormID_FormName.dat
+ CreateDocNo_DocName(Path,CaseID); //產生DocNo_Name.dat
+ Doc_Data := CreateDocNo_Info(CaseID); //產生保管袋文件 Docno,份數,頁數;Docno,份數,頁數 的回傳字串
+ Doc_Data1 := CreateCustDocNo_Info(CaseID); //產生自定文件 Docname,份數,頁數;Docno,份數,頁數 的回傳字串
+ In_Doc1 := CreateDocnoFrom_Info(CaseID); //產生被引進的保管袋文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+ In_Doc2 := CreateCustDocNoFrom_Info(CaseID); //產生被引進的自定文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+ AttachYN := CreateAttach_Info(CaseID); //是否還有附件 Y:有 N:沒有
+ ReadCaseIndex(Path);
+ //LoanDoc := 'Y';
+ //產生遮罩影像
+// if FWork_No = 'CW' then
+// HaveMask := Case2Mask(Path,MaskPath);
+ //產生遮罩影像
+ // S := S +#13+'5-->'+ Timetostr(now);
+
+ ///////必要formid 20170315 start //////////////////////////////
+ must_formidStr:='';
+ last_add_formidstr:='';
+ ST1:=TStringList.Create;
+ ST1.LoadFromFile(path+'FormCode_Name.dat');
+//ShowMessage(ST1.Text);
+//ShowMessage(LastInitFormidList.Text);
+ ST2:=TStringList.Create;
+ ST3:=TStringlist.Create;
+
+ for I := 0 to ST1.Count - 1 do
+ begin
+ if (Pos('_',St1.Strings[i])<>1) and (Pos('_',St1.Strings[i])<>-1) then
+ begin
+ str1:=Copy(ST1.Strings[i],1,Pos('_',St1.Strings[i])-1);
+ ST2.Add(str1);
+ must_formidStr:= must_formidStr+str1+'@#,';
+ end;
+ end;
+ must_formidStr:=Copy(must_formidStr,1,Length(must_formidStr)-3) ;
+//ShowMessage('must_formidStr='+must_formidStr);
+//ShowMessage('AST2='+ST2.Text);
+
+
+ for I := 0 to LastInitFormidList.Count - 1 do
+ begin
+ if ST2.IndexOf(LastInitFormidList.Strings[i]) <> -1 then
+ begin
+ ST2.Delete(ST2.IndexOf(LastInitFormidList.Strings[i]));
+ end;
+ end;
+//ShowMessage('BST2='+ST2.Text);
+ for I := 0 to ST2.Count - 1 do
+ begin
+ last_add_formidstr:=last_add_formidstr+ST2.Strings[i]+'@#,';
+ end;
+ last_add_formidstr:=Copy(last_add_formidstr,1,Length(last_add_formidstr)-3) ;
+
+ ST3.LoadFromFile(path+'scanlist.dat');
+ for I := 0 to ST3.Count - 1 do
+ begin
+ if ScanListStr = '' then
+ ScanListStr := FileName2FormCode(ST3.Strings[i])
+ else
+ ScanListStr := Format('%s,%s',[ScanListStr,FileName2FormCode(ST3.Strings[i])]);
+ end;
+
+ ST1.Free;
+ ST2.Free;
+ ST3.Free;
+//ShowMessage('last_add_formidstr='+last_add_formidstr);
+ ///////必要formid 20170315 end //////////////////////////
+
+ ///保留外部影像 start///////////////////////////////
+ casepath:= Copy(Path,1,pos('Upload',path)-1);
+//ShowMessage('casepath='+casepath);
+//FIsExternal:='Y';
+ if (FMode='ESCAN') and (FIsExternal='Y') then
+ begin
+ if FileExists(casepath+'Download\FirstImg.zip') then
+ begin
+ CopyFile(PWChar(casepath+'Download\FirstImg.zip'),PWChar(path+'FirstImg.zip'),false);
+ end
+ else
+ begin
+ CopyFile(PWChar(casepath+'Download\'+CaseID+'.zip'),PWChar(path+'FirstImg.zip'),false);
+ end;
+ end;
+ ///保留外部影像 end///////////////////////////////
+
+ //file_size 計算 就先不做 20170316
+ filesizeInt:=0;
+
+
+ //////壓檔/////
+ ZipMainFile(Path,Path,'Img.zip');
+ if HaveMask then
+ ZipMaskFile(Path,MaskPath,Path,'MaskImg.zip'); //有遮罩設定的才產生
+ /////壓檔////
+ ///檢查上傳的zip大小////
+ FName :=Path+ 'Img.zip';
+
+ FindFirst(FName, faAnyfile, FileRec);
+
+ //FMaxUploadSize
+//ShowMessage(IntToStr(FileRec.Size));
+//Result:=False;
+//exit; //目前上傳檔案大小為xxMB,已超過50MB,無法上傳 %.3f ,[FileRec.Size / 1048576]
+ If FileRec.Size > StrtoInt(FMaxUploadSize) * 1048576 Then // 檢查檔案大小
+ Begin
+ ShowMessage(Format(_Msg('%s目前上傳檔案大小為%.3fMB,已超過%sMB,無法上傳'),[caseid,FileRec.Size / 1048576,FMaxUploadSize]));
+ //ShowMessage(Format('%s目前上傳檔案大小為%.3fMB,已超過'+FMaxUploadSize+'MB,無法上傳',[caseid,FileRec.Size / 1048576]) );
+ FindClose(FileRec);
+ Result := False;
+ Exit;
+ End;
+ FindClose(FileRec);
+ ///檢查上傳的zip大小////
+//ShowMessage('last_add_formidstr='+last_add_formidstr);
+ if not GetftpInfo(CaseID,'upload') then //取案件上傳方式
+ begin
+ //Showmessage(_Msg()Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+'.');
+ DownFileErrStr := _Msg('取案件上傳資訊失敗!!')+HttpErrStr;
+ Result := False;
+ Exit;
+ end;
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))
+ +'&verify='+FVerify
+ +'&form_id='+UpformID
+ +'&loan_doc='+Case_loandoc
+ +'&case_no='+TransName
+ +'&doc_data='+HTTPEncode(UTF8Encode(Doc_Data))
+ +'&doc_data1='+HTTPEncode(UTF8Encode(Doc_Data1))
+ +'&attach='+AttachYN
+ +'&case_page='+case_page
+ +'&file_size='+IntToStr(filesizeInt)
+ +'&must_formid='+must_formidStr //擁有的 formid
+ +'&last_add_formid='+last_add_formidstr //當次新加的 formid
+ +'&form_code='+ScanListStr //scanlist.dat 表單代號
+ +'&ftp_image_path='+FFtpExtraPath //加傳FTP目錄 HTTP上傳時會是空白
+ +'&in_doc1='+HTTPEncode(UTF8Encode(In_Doc1))
+ +'&in_doc2='+HTTPEncode(UTF8Encode(In_Doc2));
+
+ case TransMode of
+ tsHttp :
+ begin
+ ////上傳/////
+ ShowText := CaseID+_Msg('資料上傳中(Http),請稍候');
+ DataLoading(True,True);
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/caseupload',SendData,'file',Path+'Img.zip',FReWrite,Memo1,False) then
+ begin
+ Showmessage(Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+'.');
+ Result := False;
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(Format(_Msg('')+_Msg(''),[CaseID])+memo1.Lines.Strings[1]+'。');
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/IMGPS00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(Format(_Msg('')+_Msg('')+_Msg('閒置過久或被登出,請重新登入'),[CaseID]));
+ Result := False;
+ Exit;
+ end;
+ ////上傳////
+ end;
+ tsFtp :
+ begin
+ ShowText := CaseID+_Msg('資料上傳中(Ftp),請稍候');
+ DataLoading(True,True);
+ SetFtpInfo;
+ try
+ if not IIS_Ftp.FtpsConnect then
+ begin
+ Showmessage(Format('無法連上Ftp主機,錯誤原因:%s',[FtpErrReason]));
+ Result := False;
+ Exit;
+ end;
+ if not IIS_Ftp.FtpsToMain(FFtpExtraPath,CaseID+'.zip',Path+'Img.zip',display1) then
+ begin
+ Showmessage(Format(_msg('上傳案件(%s)時,發生錯誤,錯誤原因:%s'),[CaseID,FtpErrStr]));
+ Result := False;
+ Exit;
+ end;
+
+ if not FtpCaseComplete(SendData) then //Ftp上傳後通知完成
+ begin
+ Showmessage(Format(_Msg('通知案件(%s)Ftp上傳完成時,發生錯誤!!'),[CaseID])+HttpErrStr);
+ Result := False;
+ Exit;
+ end;
+ finally
+ IIS_Ftp.FtpsClose;
+ end;
+ end;
+
+ end;
+
+
+ if FMode = 'ESCAN' then //上傳舊件引入檔案 //20140616 原本先搬舊件再搬新件,改為先搬新件再搬舊件
+ begin
+ if not TransOldCaseFile(ImageSavePath+CaseID+'\') then
+ begin
+ Result := False;
+ Exit;
+ end;
+ end;
+ // 呼叫Server完成 /////
+ {If not CaseComplete(Path,CaseID,MainCase) Then
+ begin
+ Showmessage(_Msg('通知案件傳送完成時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Result := False;
+ Exit;
+ end; }
+ /// 呼叫Server完成////
+
+ ////刪檔////
+ //_DelTree(Path); //會只刪TransPath
+//ShowMessage('STOP');
+ _DelTree(ImageSavePath+CaseID);
+ SetCaseList('D',-1,CaseID);
+ ////刪檔////
+end;
+
+Function TCB_IMGPSScanX.GetNoNameCase(Path:String):String; //取未配號XXXX
+var
+ i : Integer;
+begin
+ for i := 1 to 9999 do
+ begin
+ if Not DirectoryExists(Path+_Msg('未配號')+Add_Zoo(i,4)) then
+ begin
+ Result := _Msg('未配號')+Add_Zoo(i,4);
+ Break;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CaseResort(Path:String); //案件的檔案重新排序(次文件依Docno排)
+var
+ i,n,v,v1 : Integer;
+ S,S1 : TStringlist;
+ FormID,OldName,NewName,DocNo,Doc_Type:String;
+ x : Integer;
+begin
+ S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ S.LoadFromFile(Path+'Context.dat');
+ X := 0;
+ {for I := 1 to FORM_INF_List.Count - 1 do //在FormID有設定的 //主文件 照SQL排 20101028改
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ if FormCode2FileName(FormID,S) = '' then
+ Continue;
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FileName2FormCode(S.Strings[n]) = FormID) and (Doc_Type='1') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;}
+
+ {for I := 0 to FORM_INF_List.Count - 1 do //次文件 照FormID 1~8碼+掃瞄順序排 20110512為了某個文件要先打的原因要求改
+ begin
+ for n := 0 to S.Count - 1 do
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ if (S.Strings[n][1] <> '*') and (Copy(FileName2FormCode(S.Strings[n]),1,8) = Copy(FormID,1,8)) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;}
+ for I := 0 to Doc_Inf_List.Count - 1 do //主文件 照文件代碼+掃瞄順序排 20101101改 20110512晚上又說改回來
+ begin
+ DocNo := GetSQLData(Doc_Inf_List,'DOC_NO',i);
+ if DocNo2FileName(DocNo,S) = '' then
+ Continue;
+ Doc_Type := GetSQLData(Doc_Inf_List,'DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FormCode2DocNo(FileName2FormCode(S.Strings[n])) = DocNo) and (Doc_Type='1') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;
+
+
+ for I := 0 to Doc_Inf_List.Count - 1 do //次文件 照文件代碼+掃瞄順序排 20101101改 20110512晚上又說改回來
+ begin
+ DocNo := GetSQLData(Doc_Inf_List,'DOC_NO',i);
+ if DocNo2FileName(DocNo,S) = '' then
+ Continue;
+ Doc_Type := GetSQLData(Doc_Inf_List,'DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FormCode2DocNo(FileName2FormCode(S.Strings[n])) = DocNo) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;
+
+ {for n := 0 to S.Count - 1 do //次文件 照掃瞄順序排 20101028改
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ for i := 0 to FORM_INF_List.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FileName2FormCode(S.Strings[n]) = FormID) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;}
+ for i := 0 to S.Count - 1 do //FormID沒設定的或附件
+ begin
+ if S.Strings[i][1] <> '*' then
+ begin
+ Inc(X);
+ OldName := S.Strings[i];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName);
+ S.Strings[i] := '*'+S.Strings[i];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ S.Clear;
+ for i := 0 to S1.Count - 1 do //開始轉換檔名
+ begin
+ v := Pos(',',S1.Strings[i]);
+ v1 := length(S1.Strings[i]);
+ OldName := copy(S1.Strings[i],1,v-1);
+ NewName := copy(S1.Strings[i],v+1,v1-v);
+ if FileExists(Path+OldName) then
+ begin
+ ReNameFile(Path+OldName,Path+NewName);
+ S.Add(NewName);
+ S.SaveToFile(Path+'Context.dat');
+ end;
+ end;
+ ReSortFileName(Path);
+ finally
+ S.Free;
+ S1.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.DistinctDocinCase(Path:String); //列出案件裡的Docno_版本
+var
+ i,n,v : Integer;
+ S : TStringlist;
+ FormCode,DocNo,Ver : String;
+ Doc_Ver : String;
+ Exists : Boolean;
+begin
+ S := TSTringlist.Create;
+ try
+ DocNo_VerinCase.Clear;
+ S.LoadFromFile(Path+'Context.dat');
+ for I := 0 to S.Count - 1 do
+ begin
+ if FWH_category='N' then
+ begin
+ if (ISExistImg(Path+S.Strings[i])) or (reSizeExistImgList.IndexOf(LoadFileGetMD5(Path+S.Strings[i]))<>-1) then
+ begin
+ Continue;
+ end;
+ end;
+ FormCode := FileName2FormCode(S.Strings[i]);
+ DocNo := FormCode2DocNo(FormCode);
+ Ver := FormCode2Version(FormCode);
+ if (Docno <> '') and (Ver <> '') then
+ begin
+ Doc_Ver := DocNo+'_'+Ver;
+ Exists := False;
+ for n := 0 to DocNo_VerinCase.Count-1 do
+ begin
+ if Doc_Ver = DocNo_VerinCase.Strings[n] then
+ begin
+ Exists := True;
+ Break;
+ end;
+ end;
+ if not Exists then
+ DocNo_VerinCase.Add(Doc_Ver);
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.DistinctDocNoinCase(Path:String); //列出案件裡的Docno
+var
+ i,n,v : Integer;
+ S : TStringlist;
+ FormCode,DocNo,Ver : String;
+ Exists : Boolean;
+begin
+ S := TSTringlist.Create;
+ try
+ CaseDocNoList.Clear;
+ S.LoadFromFile(Path+'Context.dat');
+ for I := 0 to S.Count - 1 do
+ begin
+ FormCode := FileName2FormCode(S.Strings[i]);
+ DocNo := FormCode2DocNo(FormCode);
+ if (Docno <> '') then
+ begin
+ Exists := False;
+ for n := 0 to CaseDocNoList.Count-1 do
+ begin
+ if DocNo = CaseDocNoList.Strings[n] then
+ begin
+ Exists := True;
+ Break;
+ end;
+ end;
+ if not Exists then
+ CaseDocNoList.Add(DocNo);
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.SetCaseList(Mode:Char;Index:Integer;text:String); //'A:加入,I:插入,D:刪除,E:修改'
+var
+ i : Integer;
+begin
+ CaseList.Clear;
+ if FileExists(ImageSavePath + 'CaseList.dat') then
+ CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
+ case Mode of
+ 'A':begin
+ CaseList.Add(Text);
+ end;
+ 'I':begin
+ CaseList.Insert(Index,Text);
+ end;
+ 'E':begin
+ CaseList.Strings[Index] := Text;
+ end;
+ 'D':begin
+ if Index <> -1 then
+ CaseList.Delete(Index)
+ Else if (text <> '') then
+ begin
+ for i := 0 to CaseList.Count - 1 do
+ begin
+ if Text = CaseList.Strings[i] then
+ begin
+ CaseList.Delete(i);
+ Break;
+ end;
+ end;
+ end;
+ if CaseList.Count = 0 then
+ DeleteFile(ImageSavePath + 'CaseList.dat');
+ end;
+ end;
+ if CaseList.Count > 0 then
+ CaseList.SaveToFile(ImageSavePath+'CaseList.dat');
+end;
+
+Procedure TCB_IMGPSScanX.SetDocNoList(Mode:Char;Index:Integer;CaseNo,DocDir,Copies:String); //'A:加入,I:插入,D:刪除,E:修改'
+var
+ i : Integer;
+ CaseDocNoList : TStringlist;
+ CaseDocNo_copiesList : TStringlist;
+begin
+ CaseDocNoList := TStringlist.Create;
+ CaseDocNo_CopiesList := TStringlist.Create;
+ try
+ CaseDocNoList.Clear;
+ if FileExists(ImageSavePath+CaseNo+'\CaseDocNo.dat') then
+ CaseDocNoList.LoadFromFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');
+ if FileExists(ImageSavePath+CaseNo+'\CaseDocNo_Copies.dat') then
+ CaseDocNo_CopiesList.LoadFromFile(ImageSavePath+CaseNo+'\CaseDocNo_Copies.dat');
+ case Mode of
+ 'A':begin
+ CaseDocNoList.Add(DocDir);
+ CaseDocNo_CopiesList.Add(Copies);
+ SetRecordEditedDocDir('A',CaseNo,DocDir);
+ end;
+ 'I':begin
+ CaseDocNoList.Insert(Index,DocDir);
+ CaseDocNo_CopiesList.Insert(Index,Copies);
+ end;
+ 'E':begin
+ CaseDocNoList.Strings[Index] := DocDir;
+ CaseDocNo_CopiesList.Strings[Index] := Copies;
+ end;
+ 'D':begin
+ if Index <> -1 then
+ begin
+ //SetRecordEditedDocDir('D',CaseNo,CaseDocNoList.Strings[Index]); //20140624 修改刪除文件時也記一筆異動,刪掉會無法通知前端網頁有異動
+ SetRecordEditedDocDir('A',CaseNo,CaseDocNoList.Strings[Index]); //20170912 要刪除 不然我寫不下去
+
+ CaseDocNoList.Delete(Index);
+ CaseDocNo_CopiesList.Delete(Index);
+
+ end
+ Else if (DocDir <> '') then
+ begin
+ for i := 0 to CaseDocNoList.Count - 1 do
+ begin
+ if DocDir = CaseDocNoList.Strings[i] then
+ begin
+ //SetRecordEditedDocDir('D',CaseNo,CaseDocNoList.Strings[i]); //20140624 修改刪除文件時也記一筆異動,刪掉會無法通知前端網頁有異動
+ SetRecordEditedDocDir('A',CaseNo,CaseDocNoList.Strings[i]); //20170912 要刪除 不然我寫不下去
+ CaseDocNoList.Delete(i);
+ CaseDocNo_CopiesList.Delete(i);
+ Break;
+ end;
+ end;
+ end;
+ if ContextList.Count = 0 then
+ begin
+ DeleteFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');
+ end;
+ end;
+ end;
+ //Showmessage('abc'+#13+ImageSavePath+CaseNo+'\CaseDocNo.dat'+#13+inttostr(CaseDocNoList.Count)+#13+CaseDocNoList.Text);
+ if CaseDocNoList.Count >= 0 then
+ begin
+ CaseDocNoList.SaveToFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');
+ CaseDocNo_CopiesList.SaveToFile(ImageSavePath+CaseNo+'\CaseDocNo_Copies.dat');
+ //Showmessage('存了');
+ end;
+ finally
+ CaseDocNoList.Free;
+ CaseDocNo_CopiesList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.checkCaseOMRDone:Boolean; //檢查案件是否完成OMR檢核
+var
+ i : Integer;
+begin
+ Result := True;
+ for I := 0 to NewTreeNode.Count - 1 do
+ begin
+ if NewTreeNode.Item[i].ImageIndex <> 7 then
+ begin
+ Result := False;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckCaseID_OK:Boolean; //檢查是否有未配號的案件
+var
+ i,n : Integer;
+begin
+ Result := True;
+ for i := 0 to NewTreeNode.Count - 1 do
+ begin
+ if Pos(_msg('未配號'),NewTreeNode.Item[i].Text) > 0 then
+ begin
+ Result := False;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckCaseAttach_OK:Boolean; //檢查是否有未歸類的案件
+var
+ i,j : Integer;
+begin
+ Result := True;
+ for i := 0 to NewTreeNode.Count - 1 do
+ begin
+ for j := 0 to NewTreeNode.Item[i].Count - 1 do
+ begin
+ if Pos(_msg('未歸類'),NewTreeNode.Item[i].Item[j].Text) > 0 then
+ begin
+ Result := False;
+ Break;
+ end;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CreateEmptyCase(Path,CaseID:String); //產生空白案號(重掃件用)
+var
+ S : TStringlist;
+begin
+ S := TStringlist.Create;
+ try
+ S.SaveToFile(Path+CaseID+'\Context.dat');
+ S.Add(FCaseID);
+ S.SaveToFile(Path+'CaseList.dat')
+ finally
+ S.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ShowFileReplace(Path,NewFormID:String);//顯示的影像換成新的FormID
+var
+ i,n : Integer;
+ OldFile,NewFile:String;
+ Ext : String;
+begin
+ for i := 0 to NowShowFileList.Count - 1 do
+ begin
+ OldFile := NowShowFileList.Strings[i];
+ Ext := ExtractFileExt(OldFile);
+ NewFile := Add_Zoo(FileName2ScanPage(OldFile),3)+'_'+NewFormID+Ext;
+ ReNameFile(Path+OldFile,Path+NewFile);
+ SetContextList('E',FileName2Index(OldFile),NowCaseno,NowDocNo,NewFile);
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetCasePage(Path,CaseID:String):Integer;
+var
+ DocDirList,FileList,ST1 :TStringlist;
+ iDocDir,iDocNo : String;
+ i,n,Count : Integer;
+begin
+ Count := 0;
+ DocDirList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ ST1:=TStringList.Create;
+ try
+ if FileExists(Path+CaseID+'\CaseDocNo.dat') then
+ DocDirList.LoadFromFile(Path+CaseID+'\CaseDocNo.dat');
+ //Showmessage(DocDirList.Text);
+ for i := 0 to DocDirList.Count - 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocno := DocNoDir2DocNo(iDocDir);
+ {if (((FIs_In_Wh = 'Y') and (not DocNoIs_In_WH(iDocNo))) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and (DocNoIs_In_WH(iDocNo)))) and
+ ((iDocNo <> 'Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then //非入庫掃描不看入庫文件
+ begin
+ Continue;
+ end;}
+ //if not DocNoAppear(iDocNo) then Continue; //20170817 先註解
+
+ FileList.Clear;
+ if FileExists(Path+CaseID+'\'+iDocDir+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(Path+CaseID+'\'+iDocDir+'\Context.dat');
+
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ ST1.Clear;
+ for n := 0 to FileList.Count - 1 do
+ begin
+ if ISExistImg(Path+CaseID+'\'+iDocDir+'\'+FileList.Strings[n]) then
+ begin
+ ST1.Add(FileList.Strings[n]);
+ end;
+ end;
+
+ for n := 0 to ST1.Count - 1 do
+ begin
+ if (FileList.IndexOf(ST1.Strings[n])<>-1) and (not DocNoIs_In_WH(iDocNo)) then
+ begin
+ FileList.Delete(FileList.IndexOf(ST1.Strings[n]));
+ end;
+ end;
+ end
+ Else
+ if not DocNoAppear(iDocNo) then Continue; //20180925 Hong覺得應該要加這段
+ end;
+
+
+ Count := Count+ FileList.Count;
+ end;
+ if FileExists(Path+CaseID+'\'+AttName+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(Path+CaseID+'\'+AttName+'\Context.dat');
+ Count := Count+ FileList.Count;
+ end;
+
+ Result := Count;
+ finally
+ DocDirList.Free;
+ FileList.Free;
+ ST1.free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetFile2Case(CaseID,FileName:String);
+var
+ S :TStringlist;
+begin
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(ImageSavePath+CaseID+'\Context.dat');
+ S.Add(FileName);
+ S.SaveToFile(ImageSavePath+CaseID+'\Context.dat');
+ finally
+ S.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetCase_PageCount(var CaseCount,PageCount:Integer):Boolean; //取出案件的數量及頁數
+var
+ i,n,k: Integer;
+ CaseList,DocList,FileList,ST1 : TStringlist;
+begin
+ Result := False;
+ CaseCount := 0;
+ PageCount := 0;
+ CaseList := TStringlist.Create;
+ DocList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ ST1:= TStringlist.Create;
+ try
+ ImageSavePath := ImagePath;
+ CaseList.Clear;
+ if FileExists(ImageSavePath + 'CaseList.dat') then
+ CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
+ CaseCount := CaseCount+CaseList.Count;
+//ShowMessage('ImageSavePath='+ImageSavePath+#10#13+'CaseList.Count='+IntToStr(CaseList.Count));
+ for i := 0 to CaseList.Count - 1 do
+ begin
+ DocList.Clear;
+ If FileExists(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo.dat') Then
+ DocList.LoadFromFile(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo.dat');
+//ShowMessage('DocList='+DocList.Text);
+ for n := 0 to DocList.Count - 1 do
+ begin
+//ShowMessage(DocList.Strings[n]+','+BoolToStr(DocNoAppear(DocNoDir2DocNo(DocList.Strings[n])),true));
+ if not DocNoAppear(DocNoDir2DocNo(DocList.Strings[n])) then Continue;
+ FileList.Clear;
+ If FileExists(ImageSavePath+CaseList.Strings[i]+'\'+DocList.Strings[n]+'\Context.dat') Then
+ FileList.LoadFromFile(ImageSavePath+CaseList.Strings[i]+'\'+DocList.Strings[n]+'\Context.dat');
+ PageCount := PageCount+FileList.Count;
+ end;
+ //Showmessage(inttostr(PageCount));
+ FileList.Clear;
+ If FileExists(ImageSavePath+CaseList.Strings[i]+'\'+Attname+'\Context.dat') Then
+ FileList.LoadFromFile(ImageSavePath+CaseList.Strings[i]+'\'+Attname+'\Context.dat');
+ //Showmessage(ImageSavePath+CaseList.Strings[i]+'\'+Attname+'\Context.dat');
+//Showmessage('FileList='+FileList.Text);
+ PageCount := PageCount+FileList.Count;
+//Showmessage('PageCount='+inttostr(PageCount));
+ if (FWH_category='N') and (FIs_In_Wh='Y') then //20170912 針對非入庫並當次掃描做頁數計算
+ begin
+ if FileExists(ImageSavePath+NowCaseno+'\EditedDocDir.dat') then
+ begin
+ ST1.LoadFromFile(ImageSavePath+NowCaseno+'\EditedDocDir.dat');
+ for n := 0 to ST1.Count - 1 do
+ begin
+ if ST1.Strings[n]=AttName then Continue;
+//ShowMessage(ST1.Strings[n]+','+BoolToStr(DocNoIs_In_WH(DocNoDir2DocNo(ST1.Strings[n])),true));
+ if not DocNoIs_In_WH(DocNoDir2DocNo(ST1.Strings[n])) then
+ begin
+
+ FileList.Clear;
+ if FileExists(ImageSavePath+CaseList.Strings[i]+'\'+ST1.Strings[n]+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(ImageSavePath+CaseList.Strings[i]+'\'+ST1.Strings[n]+'\Context.dat');
+ for k := 0 to FileList.Count - 1 do
+ begin
+ if not ISExistImg(ImageSavePath+CaseList.Strings[i]+'\'+ST1.Strings[n]+'\'+FileList.Strings[k]) then
+ PageCount := PageCount+1;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ Finally
+ CaseList.Free;
+ DocList.Free;
+ FileList.Free;
+ ST1.Free
+ end;
+ Result := True;
+end;
+
+Function TCB_IMGPSScanX.BarCode2CaseID : String; //Barcode依規則轉成CaseID
+var
+ i : Integer;
+ iCaseID : String;
+begin
+ Result := ''; //沒找到
+ iCaseID := '';
+ for i := 1 to MpsBarcodeinf.Count do //20180920 拿掉-1
+ begin
+ if (Length(MpsBarcodeinf.text[i]) = CaseIDLength) then
+ begin
+ iCaseID := MpsBarcodeinf.text[i];
+ Result := iCaseID;
+ Break;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.WriteCaseIndex(Path:String);
+Var
+ S : TStringlist;
+begin
+ if Path = '' then Exit;
+ S := TStringlist.Create;
+ try
+ try
+ S.Add(Case_loandoc);
+ S.SaveToFile(Path+'CaseIndex.dat');
+ except on E: Exception do
+ end;
+
+ finally
+ S.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ReadCaseIndex(Path:String);
+Var
+ S : TStringlist;
+begin
+ AddCredit1RG.ItemIndex := -1;
+ S := TStringlist.Create;
+ try
+ if FileExists(Path+'CaseIndex.dat') then
+ begin
+ S.LoadFromFile(Path+'CaseIndex.dat');
+ Case_loandoc := S.Strings[0];
+ end;
+ if (Case_loandoc = '') and (FLoanDoc_Value <> '') then
+ begin
+ Case_loandoc := FLoanDoc_Value;
+ WriteCaseIndex(Path);
+ end;
+ if Case_loandoc = 'Y' then
+ AddCredit1RG.ItemIndex := 0
+ Else if Case_loandoc = 'N' then
+ AddCredit1RG.ItemIndex := 1;
+
+ finally
+ S.Free;
+ end;
+
+end;
+
+
+procedure TCB_IMGPSScanX.ReduceLogFile; //20171011 必免log檔掌太大
+var
+ ST1:TStringlist;
+ I:integer;
+begin
+ ST1:=TStringList.Create;
+ if FileExists(LngPath+'IMGPSCheck.log') then
+ begin
+ ST1.LoadFromFile(LngPath+'IMGPSCheck.log');
+ if ST1.count>100000 then
+ begin
+ for I := 0 to 10000 do
+ begin
+ ST1.Delete(0);
+ end;
+ ST1.SaveToFile(LngPath+'IMGPSCheck.log');
+ end;
+ end;
+ ST1.Free;
+end;
+
+Procedure TCB_IMGPSScanX.ClearCaseIndex;
+begin
+ AddCredit1RG.Enabled := False;
+ AddCredit1RG.ItemIndex := -1;
+end;
+
+Function TCB_IMGPSScanX.GetDocNoDir(Path,DocNo:String):String; //取出目前DocNo的份數
+var
+ i : Integer;
+ iDocNo : String;
+begin
+ if (DocNo <> '') then
+ begin
+ i := 0;
+ Repeat
+ begin
+ inc(i);
+ iDocNo := Format('%s_%d',[DocNo,i]);
+ end;
+ until not DirectoryExists(Path+iDocNo);
+ Result := iDocNo;
+ end
+ Else
+ begin
+ Result := AttName;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNo2DocNoDir(Path,DocNo:String):String; //DocNo轉成DocNo(份數)目錄
+var
+ i : Integer;
+ iDocNo : String;
+begin
+ if (DocNo <> '') then
+ begin
+ i := 0;
+ Repeat
+ begin
+ inc(i);
+ iDocNo := Format('%s(%d)',[DocNo,i]);
+ end;
+ until not DirectoryExists(Path+iDocNo);
+ Result := iDocNo;
+ end
+ Else
+ begin
+ Result := AttName;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNoDir2DocNo(DocNoDir:String):String; //DocNo(份數)目錄轉成DocNo
+var
+ v,ln : Integer;
+begin
+ if (DocNoDir <> 'Attach') and (DocNoDir <> 'S_Attach') then
+ begin
+ v := Pos('(',DocNoDir);
+ if v > 0 then
+ Result := Copy(DocNoDir,1,v-1)
+ else
+ Result := DocNoDir;
+ end
+ Else
+ Result := DocNoDir
+end;
+
+Function TCB_IMGPSScanX.DocNoDir2Index(Path,DocNoDir:String):Integer; //DocNo(份數)目錄轉成index
+var
+ i : Integer;
+ CaseNo_List : TStringlist;
+begin
+ Result := -1;
+ CaseNo_List := TStringlist.Create;
+ try
+ CaseNo_List.LoadFromFile(Path+'CaseDocNo.dat');
+ for i := 0 to CaseNo_List.Count - 1 do
+ begin
+ if DocNoDir = CaseNo_List.Strings[i] then
+ begin
+ Result := i;
+ Break;
+ end;
+ end;
+ finally
+ CaseNo_List.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ZipMainFile(SoPath,DePath,ZipName:String);
+var
+ ZipFileList : TStringlist;
+ n : Integer;
+begin
+ ZipFileList := TStringlist.Create;
+ try
+ if fileExists(DePath+ZipName) then
+ DeleteFile(DePath+ZipName);
+ {if FileExists(SoPath+'ReSize.dat') then
+ DeleteFile(SoPath+'ReSize.dat');}
+ //Showmessage(SoPath+#13+ContextList.Text);
+ for n := 0 to ContextList.Count - 1 do
+ begin
+ {WriteResize(SoPath+ContextList.Strings[n],SoPath+'ReSize.dat');}
+ ZipFileList.Add(SoPath+ContextList.Strings[n]);
+ if FileExists(SoPath+'@'+ContextList.Strings[n]) then
+ ZipFileList.Add(SoPath+'@'+ContextList.Strings[n]);
+ end;
+ if FileExists(SoPath+'Context.dat') then
+ ZipFileList.Add(SoPath+'Context.dat');
+
+ AttContextList.Clear;
+ if FileExists(SoPath+'ATTContext.dat') then
+ AttContextList.LoadFromFile(SoPath+'ATTContext.dat');
+ for n := 0 to AttContextList.Count - 1 do
+ begin
+ ZipFileList.Add(SoPath+AttContextList.Strings[n]);
+ end;
+ if FileExists(SoPath+'ATTContext.dat') then
+ ZipFileList.Add(SoPath+'ATTContext.dat');
+
+
+ if FileExists(SoPath+'Context_DocNo.dat') then
+ ZipFileList.Add(SoPath+'Context_DocNo.dat');
+ if FileExists(SoPath+'scanlist.dat') then
+ ZipFileList.Add(SoPath+'scanlist.dat');
+ if FileExists(SoPath+'FormCode_Name.dat') then
+ ZipfileList.Add(SoPath+'FormCode_Name.dat');
+ if FileExists(SoPath+'DocNo_Name.dat') then
+ ZipfileList.Add(SoPath+'DocNo_Name.dat');
+ if FileExists(SoPath+'ReSize.dat') then
+ ZipfileList.Add(SoPath+'ReSize.dat');
+ if FileExists(SoPath+'FormIDReplace.dat') then
+ ZipfileList.Add(SoPath+'FormIDReplace.dat');
+ if FileExists(SoPath+'AnchorError.dat') then
+ ZipfileList.Add(SoPath+'AnchorError.dat');
+ if FileExists(SoPath+'CaseDocNo.dat') then
+ ZipfileList.Add(SoPath+'CaseDocNo.dat');
+ if FileExists(SoPath+'CaseDocNo_Copies.dat') then
+ ZipfileList.Add(SoPath+'CaseDocNo_Copies.dat');
+ if FileExists(SoPath+'CustomDocNo.ini') then
+ ZipfileList.Add(SoPath+'CustomDocNo.ini');
+ if FileExists(SoPath+'DocDir.dat') then
+ ZipfileList.Add(SoPath+'DocDir.dat');
+ if FileExists(SoPath+'In_Wh.dat') then
+ ZipfileList.Add(SoPath+'In_Wh.dat');
+ if FileExists(SoPath+'UseCase.ini') then
+ ZipfileList.Add(SoPath+'UseCase.ini');
+
+ if FileExists(SoPath+'FirstImg.zip') then//20170315 加的
+ begin
+ ZipfileList.Add(SoPath+'FirstImg.zip');
+ end;
+
+
+ ExeCuteZip(DePath+ZipName,SoPath,ZipFileList,False,False);
+ //Showmessage('111');
+ finally
+ ZipFileList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ZipMaskFile(SoPath,MarkPath,DePath,ZipName:String); //壓縮遮罩影像檔
+var
+ ZipFileList : TStringlist;
+ n : Integer;
+begin
+ ZipFileList := TStringlist.Create;
+ try
+ if fileExists(DePath+ZipName) then
+ DeleteFile(DePath+ZipName);
+
+ for n := 0 to ContextList.Count - 1 do
+ begin
+ ZipFileList.Add(MarkPath+ContextList.Strings[n]);
+ end;
+ if FileExists(SoPath+'Context.dat') then
+ ZipFileList.Add(SoPath+'Context.dat');
+ if FileExists(SoPath+'scanlist.dat') then
+ ZipFileList.Add(SoPath+'scanlist.dat');
+ if FileExists(SoPath+'FormCode_Name.dat') then
+ ZipfileList.Add(SoPath+'FormCode_Name.dat');
+ if FileExists(SoPath+'DocNo_Name.dat') then
+ ZipfileList.Add(SoPath+'DocNo_Name.dat');
+ if FileExists(SoPath+'ReSize.dat') then
+ ZipfileList.Add(SoPath+'ReSize.dat');
+ if FileExists(SoPath+'Err.jpg') then
+ ZipfileList.Add(SoPath+'Err.jpg');
+ if FileExists(SoPath+'auth.jpg') then
+ ZipfileList.Add(SoPath+'auth.jpg');
+ ExeCuteZip(DePath+ZipName,SoPath,ZipFileList,False,False);
+ finally
+ ZipFileList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.MemoInfoTransfer(Mode,Str:String;ID_S,Name_S:TStringlist):String; //註記代碼註記類別轉換 Mode 'ID':代碼轉名稱;'NAME':名稱轉代碼
+var
+ i : Integer;
+begin
+ if Mode = 'ID' then
+ begin
+ Result := _Msg('自行輸入');
+ for i := 0 to ID_S.Count - 1 do
+ begin
+ if Str = ID_S.Strings[i] then
+ begin
+ Result := Name_S.Strings[i];
+ Break;
+ end;
+ end;
+ end
+ else if Mode = 'NAME' then
+ begin
+ Result := '00';
+ for i := 0 to Name_S.Count - 1 do
+ begin
+ if Str = Name_S.Strings[i] then
+ begin
+ Result := ID_S.Strings[i];
+ Break;
+ end;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetSQLData(ColumeStr:String;FromList,ToList:TStringlist); //把SQL值塞入
+var
+ i : Integer;
+begin
+ ToList.Clear;
+ ToList.Add(ColumeStr);
+ For i := 1 to FromList.Count -1 do
+ begin
+ ToList.Add(FromList.Strings[i]);
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetSQLData(TableList:TStringlist;Colname:String;colNo:Integer):String; //依欄位及索引取值
+var
+ i,col,v,v1 : Integer;
+ ColStr,DataStr: TStringList;
+ TmpStr : String;
+ P1,p2 : Integer;
+begin
+ Result := '';
+ ColStr := TStringList.Create;
+ DataStr := TSTringList.Create;
+ ColStr.CommaText := TableList.Strings[0];
+ TmpStr := TableList.Strings[ColNo];
+ //DataStr.Text:=StringReplace(TmpStr,'!@!',#13,[rfReplaceAll]);
+
+ While Length(Tmpstr) > 0 do
+ begin
+ v:= Pos('!@!',TmpStr);
+ v1 := Length(TmpStr);
+ If v > 0 Then
+ begin
+ DataStr.Add(Copy(TmpStr,1,v-1));
+ TmpStr := Copy(TmpStr,v+3,V1-(V-2));
+ end
+ Else
+ begin
+ DataStr.Add(TmpStr);
+ TmpStr := '';
+ end;
+ end;
+ For i := 0 to ColStr.Count-1 do
+ begin
+ IF ColStr.Strings[i] = ColName Then
+ begin
+ Result := '';
+ If (DataStr.Count > 0) and (i<=DataStr.Count-1) Then
+ Result := DataStr.Strings[i];
+ //If (DataStr.Count > 0) and (i<=DataStr.Count-1) Then
+ //begin
+ {if i = 0 then
+ begin
+ P1 := 1;
+ p2 := PosN('!@!',TmpStr,1)-1;
+ end
+ else
+ begin
+ P1 := PosN('!@!',TmpStr,i)+3;
+ p2 := PosN('!@!',TmpStr,i+1)-p1;
+ end;
+
+
+ Result :=Copy(tmpstr,p1,p2);}
+ //end;
+ //Result := DataStr.Strings[i];
+
+ Break;
+ end;
+ end;
+ ColStr.Free;
+ DataStr.Free;
+end;
+
+Function TCB_IMGPSScanX.FindSQLData(TableList:TStringlist;ColumeStr,KeyColumeStr,KeyStr:String;ColNo:Integer;Var ResultList:TStringlist):Boolean; //找指定的資料
+Var i,n,Findindex : Integer;
+ ColList,KeyColList,KeyList : TStringlist;
+ Cols,Keycols,keys :String;
+ Find:Boolean;
+begin
+ ResultList.Clear;
+ if (KeyStr = '') or (TableList.Count <= 1) then
+ begin
+ Result := False;
+ Exit;
+ end;
+
+ ColList := TStringlist.Create;
+ KeyColList := TStringlist.Create;
+ KeyList := TStringlist.Create;
+ try
+ ColList.CommaText := ColumeStr;
+ KeyColList.CommaText := KeyColumeStr;
+ KeyList.CommaText := KeyStr;
+ if ColNo = 0 then
+ begin
+ for i := 1 to TableList.Count -1 do //找key對不對
+ begin
+ Findindex := i;
+ for n := 0 to KeyColList.Count - 1 do
+ begin
+ Find := True;
+ Keycols := KeyColList.Strings[n];
+ keys := KeyList.Strings[n];
+ //Showmessage(keys);
+ //Showmessage(TableList.Strings[i]);
+ if GetSQLData(TableList,Keycols,i) = keys then //對.繼續
+ //if Pos('!@!'+keys+'!@!','!@!'+TableList.Strings[i]+'!@!') >0 then //在資料列前後加!@! 用pos的方式來改善速度 //20130521發現找資料會有問題
+ Continue
+ Else //不對.離開
+ begin
+ Find := False;
+ Break;
+ end;
+ end;
+ if Find then Break; // 找到了離開
+ end;
+ end
+ Else
+ begin
+ i := ColNo;
+ Findindex := i;
+ for n := 0 to KeyColList.Count - 1 do
+ begin
+ Find := True;
+ Keycols := KeyColList.Strings[n];
+ keys := KeyList.Strings[n];
+ //if GetSQLData(TableList,Keycols,i) = keys then //對.繼續
+ if Pos('!@!'+keys+'!@!','!@!'+TableList.Strings[i]+'!@!') >0 then //在資料列前後加!@! 用pos的方式來改善速度
+ Continue
+ Else //不對.離開
+ begin
+ Find := False;
+ Break;
+ end;
+ end;
+ end;
+ if Find then //有找到key
+ begin
+ for n := 0 to ColList.Count -1 do
+ begin
+ Cols := ColList.Strings[n];
+ ResultList.Add(Cols+','+GetSQLData(TableList,Cols,Findindex));
+ end;
+ end;
+ finally
+ Result := Find;
+ ColList.Free;
+ KeyColList.Free;
+ KeyList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.DataLoading(Loading:Boolean;UseTimer:Boolean); //資料載入中要停止點選的動作
+begin
+ If Loading Then
+ begin
+ Screen.Cursor := -11;
+ if UseTimer then
+ begin
+ Panel22.Caption := ShowText;
+ Panel22.Left := (Panel9.Width div 2) - (Panel22.Width div 2);
+ Panel22.Top := (Panel9.Height div 2) - (Panel22.Height div 2);
+ Panel22.Visible := True;
+ Timer2.Enabled := True;
+ end
+ Else
+ begin
+ Panel8.Left := (Panel9.Width div 2) - (Panel8.Width div 2);
+ Panel8.Top := (Panel9.Height div 2) - (Panel8.Height div 2);
+ Panel8.Visible := True;
+ end;
+ Application.ProcessMessages;
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ end
+ Else
+ begin
+ Panel22.Visible := False;
+ Panel8.Visible := False;
+ Timer2.Enabled := False;
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ Screen.Cursor := 0;
+ end;
+
+end;
+
+function TCB_IMGPSScanX.LoadFileGetMD5(const filename: string): string;
+var
+ Stream: TFileStream;
+ //Buffer: array[0..1023] of AnsiChar;
+ Buffer: array[0..1023] of AnsiChar;
+ TempStr: string;
+ i: Integer;
+ idmd5:TIdHashMessageDigest5; //import IdHashMessageDigest, idHash
+
+begin
+ idmd5 := TIdHashMessageDigest5.Create;
+
+ try
+ Stream := TFileStream.Create(filename, fmOpenRead);
+ Stream.Read(Buffer[0], SizeOf(Buffer));
+
+ result := idmd5.HashStreamAsHex(Stream) ;
+ finally
+ idmd5.Free;
+ Stream.Free;
+
+ end;
+end;
+
+procedure TCB_IMGPSScanX.LoadImgFile; //載入新件及替換件
+Var
+ i,v,v1,m : Integer;
+ CasePage : integer;
+ TempName : String;
+ BarName : String;
+ DocName : String;
+ //S : String;
+begin
+ ClearView(1);
+ PageLV.Clear;
+ AttListBox.Items.Clear;
+ AddAttFileLB.Enabled := False;
+ DelAttFileLB.Enabled := False;
+ DisplayPath := '';
+ ClearCaseIndex;
+ CaseHelpBtn.Visible := False;
+ //Del_Sub_NothingPath(ImageSavePath); //清掉案件目錄是空的
+ TreeView1.Items.Clear;
+ NewTreeNode := nil;
+ MyTreenode1 := nil;
+ MyTreenode2 := nil;
+ MyTreenode3 := nil;
+ NewTreeNode := TreeView1.Items.Add(nil,Format(_Msg('%s-共%d筆共%d頁'),[FModeName,0,0]));
+ NewTreenode.ImageIndex := 0;
+ NewTreenode.SelectedIndex := 0;
+ Del_Sub_NothingPath(ImageSavePath); //清掉案件目錄是空的
+ GetCase_PageCount(CaseCount,PageCount);
+ CaseList.Clear;
+ if FileExists(ImageSavePath + 'CaseList.dat') then
+ CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
+ for i := 0 to CaseList.Count - 1 do
+ begin
+ CaseDocNoList.Clear;
+ if FileExists(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo.dat') then
+ CaseDocNoList.LoadFromFile(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo.dat');
+ if not FileExists(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo_Copies.dat') then
+ begin
+ CaseDocNo_CopiesList.Clear;
+ for m := 0 to CaseDocNoList.Count - 1 do
+ begin
+ CaseDocNo_CopiesList.Add('1');
+ CaseDocNo_CopiesList.SaveToFile(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo_Copies.dat');
+ end;
+ end;
+
+ CasePage := GetCasePage(ImageSavePath,CaseList.Strings[i]);
+//ShowMessage('CasePage='+IntToStr(CasePage));
+ MytreeNode1 := TreeView1.Items.AddChild(NewTreeNode,Format(_Msg('%s-%d頁'),[CaseList.Strings[i],CasePage]));
+ MytreeNode1.ImageIndex := 1;
+ MytreeNode1.SelectedIndex := 1;
+ DrawDocItem2(MytreeNode1,CaseList.Strings[i]); //長出文件名稱的樹並傳回是否有申請書的影像
+ if Pos(_Msg('未配號'),CaseList.Strings[i]) > 0 then
+ begin
+ MytreeNode1.ImageIndex := 5;
+ MytreeNode1.SelectedIndex := 5;
+ end;
+ If FileExists(ImageSavePath+CaseList.Strings[i]+'\OMRCheckOk.dat') Then
+ begin
+ MytreeNode1.ImageIndex := 7;
+ MytreeNode1.SelectedIndex := 7;
+ CaseHelpBtn.Visible := False;
+ end
+ Else IF FileExists(ImageSavePath+CaseList.Strings[i]+'\Checkerr.ini') Then
+ begin
+ MyTreenode1.ImageIndex := 5;
+ MyTreenode1.SelectedIndex := 5;
+
+ //AllEnforceLb.Visible := True; //全部強迫送件
+ end;
+ end;
+ MyTreenode1 := nil;
+ MyTreenode2 := nil;
+ If NewTreeNode <> nil Then
+ begin
+ TreeView1.Selected := NewTreeNode;
+ NewTreeNode.Expand(False);
+ end;
+ IF (NewTreeNode <> nil) and (NewTreeNode.Count > 0) Then
+ begin
+ GetCase_PageCount(CaseCount,PageCount);
+ v := Pos('-',NewTreeNode.Text);
+ NewTreeNode.Text := Format(_Msg('%s-共%d筆共%d頁'),[Copy(NewTreeNode.Text,1,v-1),CaseCount,PageCount]);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.LoadImgFile1; //載入新件及替換件
+Var
+ i,n,v,v1,m : Integer;
+ p : integer;
+ iCaseNo,iDocNo : String;
+ TempName : String;
+ BarName : String;
+ DocName : String;
+ //S : String;
+begin
+ ClearView(1);
+ PageLV.Clear;
+ DisplayPath := '';
+ ClearCaseIndex;
+ CaseHelpBtn.Visible := False;
+ //Del_Sub_NothingPath(ImageSavePath); //清掉案件目錄是空的
+ TreeView1.Items.Clear;
+ NewTreeNode := nil;
+ MyTreenode1 := nil;
+ MyTreenode2 := nil;
+ MyTreenode3 := nil;
+ NewTreeNode := TreeView1.Items.Add(nil,Format(_Msg('%s-共%d筆共%d頁'),[FModeName,0,0]));
+ NewTreenode.ImageIndex := 0;
+ NewTreenode.SelectedIndex := 0;
+
+ Del_Sub_NothingPath(ImageSavePath); //清掉案件目錄是空的
+ GetCase_PageCount(CaseCount,PageCount);
+ CaseList.Clear;
+ if FileExists(ImageSavePath + 'CaseList.dat') then
+ CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
+ for n := 0 to CaseList.Count - 1 do
+ begin
+ iCaseNo := CaseList.Strings[n];
+ CaseDocNoList.Clear;
+ if FileExists(ImageSavePath+CaseList.Strings[n]+'\DocNoList.dat') then
+ CaseDocNoList.LoadFromFile(ImageSavePath+CaseList.Strings[n]+'\DocNoList.dat');
+
+ for m := 0 to CaseDocNoList.Count - 1 do
+ begin
+ iDocNo := CaseDocNoList.Strings[i];
+ MytreeNode1 := TreeView1.Items.AddChild(NewTreeNode,Format(_Msg('%s-%d頁'),[CaseList.Strings[n],p]));
+ MytreeNode1.ImageIndex := 1;
+ MytreeNode1.SelectedIndex := 1;
+ end;
+
+
+ ContextList.Clear;
+ Context_DocnoList.Clear;
+ If FileExists(ImageSavePath+CaseList.Strings[n]+'\Context.dat') Then
+ begin
+ ContextList.LoadFromFile(ImageSavePath+CaseList.Strings[n]+'\Context.dat');
+ if FileExists(ImageSavePath+CaseList.Strings[n]+'\Context_DocNo.dat') then
+ Context_DocnoList.LoadFromFile(ImageSavePath+CaseList.Strings[n]+'\Context_DocNo.dat')
+ else
+ begin
+ for m := 0 to ContextList.Count - 1 do
+ begin
+ Context_DocnoList.Add(FormCode2DocNo(FileName2FormCode(ContextList.Strings[m])));
+ end;
+ Context_DocnoList.SaveToFile(ImageSavePath+CaseList.Strings[n]+'\Context_DocNo.dat');
+ end;
+ Cust_DocNoList.Clear;
+ if FileExists(ImageSavePath+CaseList.Strings[n]+'\CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(ImageSavePath+CaseList.Strings[n]+'\CustomDocNo.dat');
+
+ P := ContextList.Count;
+ MytreeNode1 := TreeView1.Items.AddChild(NewTreeNode,Format(_Msg('%s-%d頁'),[CaseList.Strings[n],p]));
+ MytreeNode1.ImageIndex := 1;
+ MytreeNode1.SelectedIndex := 1;
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,CaseList.Strings[n]); //長出文件名稱的樹並傳回是否有申請書的影像
+ DrawDocItem2(MytreeNode1,CaseList.Strings[n]); //長出文件名稱的樹並傳回是否有申請書的影像 20140820改
+
+ if Pos(_Msg('未配號'),CaseList.Strings[n]) > 0 then
+ begin
+ MytreeNode1.ImageIndex := 5;
+ MytreeNode1.SelectedIndex := 5;
+ end;
+ If FileExists(ImageSavePath+CaseList.Strings[n]+'\OMRCheckOk.dat') Then
+ begin
+ MytreeNode1.ImageIndex := 7;
+ MytreeNode1.SelectedIndex := 7;
+ CaseHelpBtn.Visible := False;
+ end
+ Else IF FileExists(ImageSavePath+CaseList.Strings[n]+'\Checkerr.ini') Then
+ begin
+ MyTreenode1.ImageIndex := 5;
+ MyTreenode1.SelectedIndex := 5;
+
+ //AllEnforceLb.Visible := True; //全部強迫送件
+ end;
+ end;
+ end;
+
+
+ MyTreenode1 := nil;
+ MyTreenode2 := nil;
+ If NewTreeNode <> nil Then
+ begin
+ TreeView1.Selected := NewTreeNode;
+ NewTreeNode.Expand(False);
+ end;
+ ContextList.Clear;
+ IF (NewTreeNode <> nil) and (NewTreeNode.Count > 0) Then
+ begin
+ GetCase_PageCount(CaseCount,PageCount);
+ v := Pos('-',NewTreeNode.Text);
+ NewTreeNode.Text := Format(_Msg('%s-共%d筆共%d頁'),[Copy(NewTreeNode.Text,1,v-1),CaseCount,PageCount]);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.LoadAttFile(CaseID:String); //載入附加檔案
+var
+ AttContextList : TStringlist;
+ i : Integer;
+begin
+ AttListBox.Clear;
+ AttContextList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\AttContext.dat') then
+ begin
+ AttContextList.LoadFromFile(ImageSavePath+CaseID+'\AttContext.dat');
+ end;
+ for i := 0 to AttContextList.Count - 1 do
+ begin
+ AttListBox.Items.Add(UTF8Decode(HTTPDEcode(AttContextList.Strings[i])));
+ end;
+ finally
+ AttContextList.Free;
+ end;
+end;
+
+function TCB_IMGPSScanX.logTimeString: String;
+begin
+Result:=FormatDateTime('yyyymmdd hh:mm:ss',now) +' caseNo='+NowCaseno+' ';
+end;
+
+Function TCB_IMGPSScanX.Case2Mask(SoPath,DePath:String):Boolean;//產生遮罩影像 20170639 發現沒用到
+var
+ XT : TXMLTool;
+ i : Integer;
+ S : TStringlist;
+ SiteList : TStringlist;
+ FormID : String;
+ ColEName : String;
+ FileName : String;
+ nodename : String;
+ Site : String;
+ Anchor : String;
+begin
+ Result := False;
+ if DirectoryExists(DePath) then
+ _DelTree(DePath);
+ Str2Dir(DePath);
+ DeleteFile(SoPath+'MaskImg.zip');
+ SiteList := TStringlist.Create;
+ S := TStringlist.Create;
+ XT := TXMLTool.Create;
+ try
+ S.LoadFromFile(SoPath+'Context.dat');
+ for I := 0 to S.Count - 1 do
+ begin
+ SiteList.Clear;
+ ImageScrollBox1.LoadFromFile(SoPath+S.Strings[i],1);
+
+ FormID := FileName2FormCode(S.Strings[i]);
+ Anchor := FormID2Anchor(FormID);
+ //ParserPoint(CropMpsV.FindPoint(Anchor));
+ FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,Anchor);
+ if FileExists(CheckXmlPath+FWork_no+'\'+FormID+'.xml') then //沒有Xml就不用遮罩
+ begin
+ XT.LoadFromFile(CheckXmlPath+FWork_no+'\'+FormID+'.xml');
+ if XT.SubNodes['/form/settype10/'].First then
+ Repeat
+ ColEName := XT.SubNodes['/form/settype10/'].NodeName;
+ if XT.SubNodes['/form/settype10/'+ColEName+'/'].First then
+ Repeat
+ nodename := XT.SubNodes['/form/settype10/'+ColEName+'/'].NodeName;
+ If nodename <> '@coldesc' then
+ begin
+ Site := XT.Node['/form/settype10/'+ColEName+'/'+nodename+'/'].Attributes['colxy'];
+ SiteList.Add(Site);
+ Result := True; //有設定
+ end
+ Else
+ begin
+ //ColCName := XT['/form/settype1/'+ColEName+'/'+nodename+'/'];
+ end;
+ Until not XT.SubNodes['/form/settype10/'+ColEName+'/'].Next;
+ Until not XT.SubNodes['/form/settype10/'].Next ;
+ FieldMask(ImageScrollBox1,SiteList.Text,'Mask',UpLPoint);
+ end;
+ SaveAnnotation(ImageScrollBox1,DePath+S.Strings[i]);
+ end;
+ finally
+ SiteList.Free;
+ S.Free;
+ XT.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetNewCustomDocNo(Path,DocName:String):String; //取出未使用的自訂文件代號
+var
+ ini : Tinifile;
+ Ct:Integer;
+ DocNo,FormID : String;
+
+ {i,n,v,ln : Integer;
+ C_No,C_Name : String;
+ CNo : Integer;
+ S : TStringlist;
+ NewDocNo : String;}
+begin
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ Ct := ini.ReadInteger('CustomCount','Count',0);
+ inc(Ct);
+ DocNo := 'ZZZZZ'+Add_Zoo(Ct,3);
+ if FIs_In_Wh <> 'Y' then //不是入庫文件
+ DocNo := 'YYYYY'+Add_Zoo(Ct,3);
+
+ if (FMode='ESCAN') and (FWH_category='N') then //20170914 補件下改成非入庫的自定文件
+ begin
+ DocNo := 'YYYYY'+Add_Zoo(Ct,3);
+ end;
+
+ FormID := DocNo+'010101A';
+ ini.WriteInteger('CustomCount','Count',Ct);
+ ini.WriteString(DocNo,'FormID',FormID);
+ ini.WriteString(DocNo,'Name',DocName);
+ Result := DocNo;
+ finally
+ ini.Free;
+ end;
+
+ {S := TStringlist.Create;
+ try
+ NewDocNo :='ZZZZZ001';
+ if FileExists(Path+'CustomDocNo.dat') then
+ begin
+ /// ZZZZZ001_自定文件名稱 001_自定文件名稱
+ S.LoadFromFile(Path+'CustomDocNo.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+ v := Pos('_',S.Strings[i]);
+ ln := Length(S.Strings[i]);
+ C_No := Copy(S.Strings[i],1,v-1);
+ C_Name := Copy(S.Strings[i],v+1,ln-v);
+ if DocName = C_Name then
+ begin
+ Showmessage('文件名稱已存在');
+ Result := '';
+ Exit;
+ end;
+ end;
+ CNo := strtoint(Copy(C_No,6,3))+1;
+ NewDocNo := 'ZZZZZ'+Add_Zoo(CNo,3);
+ end;
+ S.Add(NewDocNo+'_'+DocName);
+ S.SaveToFile(Path+'CustomDocNo.dat');
+ Result := NewDocNo;
+ finally
+ S.Free;
+ end; }
+end;
+
+Function TCB_IMGPSScanX.GetCustomDocDir(Path,DocName:String):String; //取出自定文件DocDir
+var
+ i,ct:integer;
+ ini : Tinifile;
+begin
+ Result := '';
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ ct := ini.ReadInteger('CustomCount','Count',0);
+ for i := 1 to ct do
+ begin
+ if ini.ReadString('ZZZZZ'+Add_Zoo(i,3),'Name','') = DocName then
+ begin
+ Result := 'ZZZZZ'+Add_Zoo(i,3);
+ Break;
+ end;
+ if ini.ReadString('YYYYY'+Add_Zoo(i,3),'Name','') = DocName then
+ begin
+ Result := 'YYYYY'+Add_Zoo(i,3);
+ Break;
+ end;
+ end;
+ finally
+ ini.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.DeleteCustomDocDir(Path,DocNo:String); //刪除自定文件DocNo
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ ini.EraseSection(DocNo);
+ finally
+ ini.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FindLastestDocDir(CaseID,DocNo:String):String; //找出最新的DocDir
+var
+ i : Integer;
+ DocNoList,FileList : TStringlist;
+begin
+ Result := '';
+ DocNoList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ for i := DocNoList.Count-1 downto 0 do
+ begin
+ if Copy(DocNoList.Strings[i],1,length(DocNo)) = DocNo then
+ begin
+ Result := DocNoList.Strings[i];
+ Break;
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ FileList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FindLastestDocDirForPage(CaseID,DocNo,formid:String):String; //找出最新的DocDir 20180207 排除隱藏的資料夾
+var
+ i,j:integer;
+ DocNoList,FileList : TStringlist;
+ Imglist: TStringlist;
+ DirIsHide:Boolean;
+begin
+ Result := '';
+ DocNoList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ imglist := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+
+ for i := DocNoList.Count-1 downto 0 do
+ begin
+ if Copy(DocNoList.Strings[i],1,length(DocNo)) = DocNo then
+ begin
+//ShowMessage(ImageSavePath+CaseID+'\'+DocNoList.Strings[i]);
+ if not DocNoIsExistImg(ImageSavePath+CaseID+'\'+DocNoList.Strings[i]+'\') then
+ begin
+//ShowMessage('DDDDD');
+ Result := '';
+ Break;
+ end
+ else
+ begin
+ Result := DocNoList.Strings[i];
+ Break;
+ end;
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ FileList.Free;
+ imglist.Free;
+ end;
+
+end;
+
+
+Procedure TCB_IMGPSScanX.Create_Cust_DocDir(CaseID:String); //產生外面傳入的文件代號及自定文件
+var
+ i,n : Integer;
+ C_DocNoList,C_DocNameList : TStringlist;
+ DocNo,DocName,DocDir : String;
+ DocNo_Ct,NowDocNo_Ct :integer;
+ DocName_Ct : Integer;
+ inx : Integer;
+begin
+ C_DocNoList := TStringlist.Create;
+ C_DocNameList := TStringlist.Create;
+ try
+
+ if FC_DocNoList <> '' then
+ begin
+ C_DocNoList.StrictDelimiter := True;
+ C_DocNoList.Delimiter := #9;
+ C_DocNoList.DelimitedText := FC_DocNoList;
+ //Showmessage(C_DocNoList.Text);
+ for i := 0 to C_DocNoList.Count - 1 do
+ begin
+ DocNo := C_DocNoList.Strings[i];
+ //舊件不長出錯誤的文件出來
+ if (FIs_OldCase = 'Y') and (FWork_no='HLN') and (DocNo = FormCode2DocNo('10000001011112A')) then
+ Continue;
+ NowDocNo_Ct := GetDocNoCount(CaseID,DocNo);
+ if DocNoNeedDiv(DocNo) then
+ begin
+ DocNo_Ct := 0;
+ for n := 0 to i do
+ begin
+ if C_DocNoList.Strings[n] = DocNo then
+ inc(DocNo_Ct);
+ end;
+ if DocNo_CT <= NowDocNo_Ct then
+ Continue;
+ if DirectoryExists(ImageSavePath+CaseID+'\'+DocNo+'('+inttostr(DocNo_Ct)+')') then //存在了
+ Continue;
+ if (DocNo_Ct = 1) and DirectoryExists(ImageSavePath+CaseID+'\'+DocNo) then //存在了 20140327加
+ Continue;
+ DocDir := DocNo2DocNoDir(ImageSavePath+CaseID+'\',DocNo)
+
+ end
+ else
+ begin
+ DocDir := DocNo;
+ end;
+ if not DirectoryExists(ImageSavePath+CaseID+'\'+DocDir) then
+ begin
+ MkDir(ImageSavePath+CaseID+'\'+DocDir);
+ SetDocNoList('A',-1,CaseID,DocDir,'1');
+ end;
+ if not DocNoNeedDiv(DocNo) then //不分份的秀數
+ SetDocDirCopies(CaseID,DocNo,GetCustomDocNoCount(DocNo));
+
+ end;
+ end;
+ if FC_DocNameList <> '' then
+ begin
+ C_DocNameList.StrictDelimiter := True;
+ C_DocNameList.Delimiter := #9;
+ C_DocNameList.DelimitedText := FC_DocNameList;
+ //Showmessage(C_DocNameList.Text);
+ for i := 0 to C_DocNameList.Count - 1 do
+ begin
+ DocName := C_DocNameList.Strings[i];
+ DocName_Ct := GetCustomNameCount(DocName);
+ if not FindCustomDocName(ImageSavePath+CaseID+'\',DocName) then
+ begin
+ DocDir := GetNewCustomDocNo(ImageSavePath+CaseID+'\',DocName);
+ if not DirectoryExists(ImageSavePath+CaseID+'\'+DocDir) then
+ begin
+ MkDir(ImageSavePath+CaseID+'\'+DocDir);
+ SetDocNoList('A',-1,CaseID,DocDir,inttostr(DocName_Ct));
+ end;
+ end
+ Else
+ begin
+ DocDir := GetCustomDocDir(ImageSavePath+CaseID+'\',DocName);
+ //inx := DocNoDir2Index(ImageSavePath+CaseID+'\',DocDir);
+ SetDocDirCopies(CaseID,DocDir,DocName_Ct);
+ end;
+ end;
+ end;
+
+ finally
+ C_DocNoList.Free;
+ C_DocNameList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.OldCasetoNewCase(CaseID:String); //將舊案份數轉成新規則
+var
+ i,n : Integer;
+ C_DocNoList,C_DocNameList : TStringlist;
+ DocNoList,DocNo_CopiesList : TStringlist;
+ DocNo,DocName,DocDir : String;
+ DocNo_Ct :integer;
+begin
+ C_DocNoList := TStringlist.Create;
+ C_DocNameList := TStringlist.Create;
+ DocNoList := TStringlist.Create;
+ DocNo_CopiesList := TStringlist.Create;
+ try
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ DocNo_CopiesList.Add('0');
+ end;
+ //Showmessage(FC_DocNoList);
+ if FC_DocNoList <> '' then
+ begin
+ C_DocNoList.StrictDelimiter := True;
+ C_DocNoList.Delimiter := #9;
+ C_DocNoList.DelimitedText := FC_DocNoList;
+ //showmessage(C_DocNoList.Text+#13+#13+DocNoList.Text);
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ //DocNo := DocNoList.Strings[i];
+ DocNo := DocNoDir2DocNo(DocNoList.Strings[i]); //20140812 因轉舊案錯誤件會出現DocnoDir
+ DocNo_Ct := 0;
+ for n := 0 to C_DocNoList.Count - 1 do
+ begin
+ if DocNo = C_DocNoList.Strings[n] then
+ inc(DocNo_Ct);
+ end;
+ if DocNo_CT > 0 Then
+ DocNo_CopiesList.Strings[i] := inttostr(DocNo_CT);
+ end;
+ DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ end;
+ if FC_DocNameList <> '' then
+ begin
+ C_DocNameList.StrictDelimiter := True;
+ C_DocNameList.Delimiter := #9;
+ C_DocNameList.DelimitedText := FC_DocNameList;
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ DocNo := DocNoList.Strings[i];
+ DocNo_Ct := 0;
+ for n := 0 to C_DocNameList.Count - 1 do
+ begin
+ if GetCustomDocName(ImageSavePath+CaseID+'\',DocNo) = C_DocNameList.Strings[n] then
+ inc(DocNo_Ct);
+ end;
+
+ if DocNo_CT > 0 Then
+ DocNo_CopiesList.Strings[i] :=inttostr(DocNo_CT);
+ end;
+ end;
+ DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ finally
+ C_DocNoList.Free;
+ C_DocNameList.Free;
+ DocNoList.Free;
+ DocNo_CopiesList.Free;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.SetRecordEditedDocDir(Mode:Char;CaseID,DocDir:String); //記錄被異動的文件目錄 'A:加入D:刪掉'
+var
+ i : Integer;
+ Exists : Boolean;
+ EditedDocDirList : TStringlist;
+begin
+ EditedDocDirList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
+ EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
+ case Mode of
+ 'A':begin
+ Exists := False;
+ for i := 0 to EditedDocDirList.Count - 1 do
+ begin
+ if EditedDocDirList.Strings[i]=DocDir then
+ begin
+ Exists := True;
+ Break;
+ end;
+ end;
+ if not Exists then
+ begin
+ EditedDocDirList.Add(DocDir);
+ EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
+ end;
+ end;
+ 'D':begin
+ for i := 0 to EditedDocDirList.Count - 1 do
+ begin
+ if EditedDocDirList.Strings[i] = DocDir then
+ begin
+ EditedDocDirList.Delete(i);
+ if EditedDocDirList.Count > 0 then
+ EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat')
+ else
+ DeleteFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
+ Break;
+ end;
+ end;
+ end;
+ end;
+
+ finally
+ EditedDocDirList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocDir_Page(CaseID,DocDir:String):Integer;
+var
+ FileList : TStringlist;
+begin
+ Result := 0;
+ FileList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
+ Result := FileList.Count;
+ end;
+ finally
+ FileList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.Path2DocDir(Path,CaseID:String):String;
+var
+ i : Integer;
+ DocnoList : TStringlist;
+begin
+ Result := '';
+ DocNoList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ if Path[length(Path)]<>'\' then
+ path := path+'\';
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ if (path=ImageSavePath+CaseID+'\'+DocNoList.Strings[i]+'\') then
+ begin
+ Result := DocNoList.Strings[i];
+ Break;
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocNo_IS_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
+var
+ i :Integer;
+begin
+ Result := False;
+ for i := 0 to IN_WH_DocNoList.Count - 1 do
+ begin
+ if DocNo = IN_WH_DocNoList.Strings[i] then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNoIs_In_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
+var
+ i : Integer;
+begin
+ Result := False;
+ if (Copy(DocNo,1,5)='ZZZZZ') then //20140728 yuu 說自訂文件也是入庫文件
+ begin
+ Result := True;
+ Exit;
+ end;
+ for i := 0 to IN_WH_DocNoList.Count -1 do
+ begin
+ if DocNo = IN_WH_DocNoList.Strings[i] then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CreateCaseNeedData(Path:String);
+var
+ FileList,DocNoList,CaseDocNoList,CaseDocNo_CopiesList : TStringlist;
+ i,n : Integer;
+ Docno : String;
+ Exists : Boolean;
+begin
+ FileList := TStringlist.Create;
+ DocNoList := TStringlist.Create;
+ CaseDocNoList := TStringlist.Create;
+ CaseDocNo_CopiesList := TStringlist.Create;
+ try
+ if FileExists(Path+'Context.dat') then
+ begin
+ FileList.LoadFromFile(Path+'Context.dat');
+ for i := 0 to FileList.Count - 1 do
+ begin
+ Docno := FormCode2DocNo(FileName2FormCode(FileList.Strings[i]));
+//ShowMessage('Docno='+Docno);
+ DocNoList.Add(DocNo);
+ Exists := False;
+ for n := 0 to CaseDocNoList.Count - 1 do
+ begin
+ if Docno = CaseDocNoList.Strings[n] then
+ Exists := True;
+ end;
+ if not Exists then
+ begin
+ CaseDocNoList.Add(DocNo);
+ CaseDocNo_CopiesList.Add('1');
+ end;
+ end;
+//ShowMessage('CreateCaseNeedData DocNoList='+DocNoList.Text);
+ DocNoList.SaveToFile(Path+'DocDir.dat');
+ CaseDocNoList.SaveToFile(Path+'CaseDocNo.dat');
+ CaseDocNo_CopiesList.SaveToFile(Path+'CaseDocNo_Copies.dat')
+ end;
+
+ finally
+ FileList.Free;
+ DocNoList.Free;
+ CaseDocNoList.Free;
+ CaseDocNo_CopiesList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetDocDirtoSelected(CaseNode:TTreeNode;DocDir:String);
+var
+ i : Integer;
+begin
+ for i := 0 to CaseNode.Count - 1 do
+ begin
+ if Pos(DocDir+'{',CaseNode.Item[i].Text) > 0 then
+ begin
+ TreeView1.Selected := CaseNode.Item[i];
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckSelectImg_UseCase(Path,CaseID:String):Boolean; //檢查選擇的影像是否有包含被引用的影像
+var
+ i : Integer;
+ iISBName : String;
+ iISB : TImageScrollBox;
+ ImgPath,DocDir : String;
+begin
+ Result := False;
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ //Showmessage(Components[i].Name);
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+ ImgPath := ExtractFilePath(iISB.FileName);
+ DocDir := Path2DocDir(ImgPath,CaseID);
+ if GetUseCase('T',Path,DocDir) <> '' then
+ Result := True;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.TransOldCaseFile(Path:String):Boolean;
+var
+ i : Integer;
+ OldCaseID,Year,Data,Verify:String;
+ SendData : String;
+ OldCaseInfoList,Caseinfolist : TStringlist;
+ OldCasePath : String;
+begin
+ Result := True;
+ OldCaseInfoList := TStringlist.Create;
+ Caseinfolist := TStringlist.Create;
+ try
+ OldCaseInfoList.StrictDelimiter := True;
+ OldCaseInfoList.Delimiter := #9;
+ OldCaseInfoList.DelimitedText := FOldCaseInfo;
+ for i := 0 to OldCaseInfoList.Count - 1 do
+ begin
+ Caseinfolist := SplitString('@#,',OldCaseInfoList.Strings[i]);
+ //Caseinfolist.Delimiter := '_';
+ //Caseinfolist.DelimitedText := OldCaseInfoList.Strings[i];
+ OldCaseID := Caseinfolist.Strings[0];
+ Year := Caseinfolist.Strings[1];
+ Data := Caseinfolist.Strings[4];
+ Verify := Caseinfolist.Strings[5];
+ OldCasePath := Path+OldCaseID+'\';
+ if FileExists(OldCasePath+'UseCase.dat') and FileExists(OldCasePath+'UseCase.ini') then
+ begin
+ //////壓檔/////
+ //ZipMainFile(Path,Path,'Img.zip');
+
+ ////上傳/////
+ SendData:='data='+HTTPEncode(UTF8Encode(Data))+'&verify='+Verify+'&other_case_no='+OldCaseID;
+ //Showmessage(FUrl+'service/slic/SLIC02/useOther?'+senddata);
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/useOther',SendData,'file',OldCasePath+'UseCase.ini',FReWrite,Memo1,False) then
+ begin
+ Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason);
+ Result := False;
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
+ Result := False;
+ Exit;
+ end;
+ end;
+
+ ////上傳////
+ end;
+ finally
+ OldCaseInfoList.Free;
+ Caseinfolist.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.Writelog(CaseID : String):Boolean;
+var
+ SendData : String;
+begin
+ Result := True;
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&case_no='+CaseID;
+ If not ProcessServlet(HTTPSClient,FURL+'service/imgpsc/IMGPSC06/printlog',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetFtpinfo(CaseID,Action:String):Boolean;
+var
+ SendData : String;
+
+ Procedure DecodeFtpInfo(EncryStr:String);
+ var
+ FtpStr : String;
+ ftpinfoList : TStringlist;
+ begin
+ if EncryStr = '' then Exit;
+ ftpinfoList := TStringlist.Create;
+ try
+ FtpStr := En_DecryptionStr_Base64('D',EncryStr,MpsKey);
+ SplitString('!@!',FtpStr,ftpinfoList);
+ if ftpinfoList[0] = 'ftps' then
+ FFtpProtocol := fpftps
+ else if ftpinfoList[0] = 'ftp' then
+ FFtpProtocol := fpftp;
+ FFtpIP := ftpinfoList[1];
+ FFtpPort := strtoint(ftpinfoList[2]);
+ FFtpID := ftpinfoList[3];
+ FFtpPwd := ftpinfoList[4];
+
+ finally
+ ftpinfoList.Free;
+ end;
+ end;
+begin
+ Result := True;
+ SendData:='product='+FWork_no+'&case_no='+CaseID+'&department='+FUserUnit+'&action='+Action;
+ If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/ftps',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF (memo1.Lines.Strings[0] = '1') Then
+ begin
+ if memo1.Lines.Strings[1]='nodata' then //nodata 為正常可繼續的判斷
+ begin
+ TransMode := tsNone;
+ Result := True;
+ Exit;
+ end
+ else
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end
+ else if (memo1.Lines.Strings[0] <> '0') then//不認識的字串
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[0];
+ Result := False;
+ Exit;
+ end;
+ TransMode := tsHttp;
+ FFtpExtraPath := '';
+
+ if memo1.Lines.Strings[0] = '0' then
+ begin
+ if memo1.Lines.Strings[2] = 'Y' then //要使用FTP
+ TransMode := tsFtp;
+ if memo1.Lines.Count > 3 then
+ begin
+ FFtpExtraPath := memo1.Lines.Strings[3];
+ DecodeFtpInfo(memo1.Lines.Strings[4]);
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetFtpInfo; //餵入FTP資訊
+begin
+ IIS_Ftp.Display1 := Display1;
+ IIS_Ftp.FTPSClient1 := FTPSClient1;
+ IIS_Ftp.ElMemoryCertStorage := ElMemoryCertStorage;
+ IIS_Ftp.Display1 := Display1;
+ IIS_Ftp.Ftpip := FFtpIP;
+ IIS_Ftp.Ftpuserid := FFtpID;
+ IIS_Ftp.FtpPwd := FFtpPwd;
+ IIS_Ftp.FtpPath := FFtpRootPath;
+ IIS_Ftp.FtpPort := FFtpPort;
+ IIS_Ftp.FtpSSL := True;
+ IIS_Ftp.FtpPassive := True;
+ if FFtpProtocol = fpftp then
+ IIS_Ftp.FtpSSL := False;
+ IIS_Ftp.FtpEncryptDataChannel := true;
+ FTPSClient1.OnControlReceiveAsString := IIS_Ftp.EventHandlers.ControlReceiveAsString;
+ FTPSClient1.OnControlSendAsString := IIS_Ftp.EventHandlers.ControlSendAsString;
+ FTPSClient1.OnSSLError := IIS_Ftp.EventHandlers.SSLError;
+ FTPSClient1.OnCertificateValidate := IIS_Ftp.EventHandlers.CertificateValidate;
+ FTPSClient1.OnTextDataLine := IIS_Ftp.EventHandlers.TextDataLine;
+
+ {Showmessage(Format('Ftpip:%s'+#13
+ +'Ftpid:%s'+#13
+ +'Ftppwd:%s'+#13
+ +'Ftppath:%s'+#13
+ +'Ftpport:%s'+#13
+ ,[FFtpIP,FFtpid,FFtpPwd,Ftppath,inttostr(Ftpport)]));}
+end;
+
+Function TCB_IMGPSScanX.FtpCaseComplete(SendData:String):Boolean;
+begin
+ Result := True;
+ If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/caseupload',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF (memo1.Lines.Strings[0] = '1') or (memo1.Lines.Strings[0] <> '0') Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNoAppear(DocNo:String):Boolean; //DocNo是否可出現
+begin
+ Result := True;
+
+ {if (((FIs_In_Wh = 'Y') and (not DocNoIs_In_WH(DocNo)) or (DocNo ='S_Attach')) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and (DocNoIs_In_WH(DocNo)) or (DocNo ='Attach') )) {and //非入庫掃描不看入庫文件
+ (Copy(DocNo,1,5)<>'ZZZZZ')} {then
+ {Result := False;}
+ //20181031 應該要換成下面的判斷比較對,FIs_In_Wh傳空的話才會出全部
+ if (((FIs_In_Wh = 'Y') and ((not DocNoIs_In_WH(DocNo)) or (DocNo ='S_Attach'))) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and ((DocNoIs_In_WH(DocNo)) or (DocNo ='Attach') ))) {and //非入庫掃描不看入庫文件
+ (Copy(DocNo,1,5)<>'ZZZZZ')} then
+ Result := False;
+
+
+end;
+
+Function TCB_IMGPSScanX.GetDocNoCount(CaseID,DocNo:String):Integer; //取DocNo數量
+var
+ i : Integer;
+ Doc_Ct:Integer;
+ iDocNo : String;
+ DocNoList,DocNo_CopiesList : TStringlist;
+begin
+ DocNoList := TStringlist.Create;
+ DocNo_CopiesList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ begin
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ end;
+ Doc_Ct := 0;
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ iDocNo := DocNoDir2DocNo(DocNoList.Strings[i]);
+ if iDocNo = DocNo then
+ Doc_Ct := Doc_Ct + strtoint(DocNo_CopiesList.Strings[i]);
+ end;
+ Result := Doc_Ct;
+ // Showmessage(DocNo+#13+inttostr(Doc_Ct));
+ finally
+ DocNoList.Free;
+ DocNo_CopiesList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocDirCopies(CaseID,DocDir:String):Integer; //取DocDir數量
+var
+ i : Integer;
+ DocNoList,DocNo_CopiesList : TStringlist;
+begin
+ Result := 1; //預設回傳1 //20140521 由0改成1
+ DocNoList := TStringlist.Create;
+ DocNo_CopiesList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat') then
+ begin
+ DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ if (DocDir = DocNoList.Strings[i]) and (i <= DocNo_CopiesList.Count-1) then
+ begin
+ Result := strtoint(DocNo_CopiesList.Strings[i]);
+ Break;
+ end;
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ DocNo_CopiesList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetDocDirCopies(CaseID,DocDir:String;NewCopies:Integer); //修改DocDir份數
+var
+ i : Integer;
+ DocNoList,DocNo_CopiesList : TStringlist;
+begin
+ DocNoList := TStringlist.Create;
+ DocNo_CopiesList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ begin
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ end;
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ if DocDir = DocNoList.Strings[i] then
+ begin
+ DocNo_CopiesList.Strings[i] := inttostr(NewCopies);
+ DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ Break;
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ DocNo_CopiesList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocDirCopies_Rec(Path,CaseID,DocDir:String):Integer; //取記錄裡的DocDir份數
+var
+ i,n,v,v1 : Integer;
+ OldCaseInfoList,Caseinfolist : TStringlist;
+ iCaseID,Year,iBS_No,iIS_Old,iDocNo,iCopies:String;
+begin
+ Result := 1;
+ OldCaseInfoList := TStringlist.Create;
+ Caseinfolist := TStringlist.Create;
+ try
+ //OldCaseInfoList 案件編號@#,年度@#,業務別@#,是否舊件@#,Data@#,Verify@#,文件編號[份數]@#,文件編號[份數] tab 案件編號@#,年度@#,業務別@#,是否舊件@#,Data@#,Verify@#,文件編號[份數]@#,文件編號[份數]
+ OldCaseInfoList.StrictDelimiter := true;
+ OldCaseInfoList.Delimiter := #9;
+ OldCaseInfoList.DelimitedText := FOldCaseInfo;
+
+ for i := 0 to OldCaseInfoList.Count - 1 do
+ begin
+ Caseinfolist:=SplitString('@#,',OldCaseInfoList.Strings[i]);
+ //Caseinfolist.Delimiter := '_';
+ //Caseinfolist.DelimitedText := OldCaseInfoList.Strings[i];
+ iCaseID := Caseinfolist.Strings[0];
+ Year := Caseinfolist.Strings[1];
+ iBS_No := Caseinfolist.Strings[2];
+ iIS_Old := Caseinfolist.Strings[3];
+ if CaseID = iCaseID then
+ begin
+ for n := 6 to Caseinfolist.Count - 1 do
+ begin
+ v := Pos('[',Caseinfolist.Strings[n]);
+ v1 := Pos(']',Caseinfolist.Strings[n]);
+ iDocNo := Copy(Caseinfolist.Strings[n],1,v-1);
+ iCopies := Copy(Caseinfolist.Strings[n],v+1,v1-v-1);
+ if Copy(DocDir,1,5) = 'ZZZZZ' then
+ begin
+ if iDocNo = GetCustomDocName(Path,DocDir) then
+ Result := strtoint(iCopies);
+ end
+ else
+ begin
+ if iDocNo = DocNoDir2DocNo(DocDir) then
+ Result := strtoint(iCopies);
+ end;
+ end;
+
+ end;
+ end;
+ finally
+ OldCaseInfoList.Free;
+ Caseinfolist.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetCustomDocNoCount(Docno:String):Integer; //取外傳的DocNo數量
+var
+ i,ct : Integer;
+ C_DocNoList : TStringlist;
+begin
+ C_DocNoList := TStringlist.Create;
+ try
+ C_DocNoList.StrictDelimiter := True;
+ C_DocNoList.Delimiter := #9;
+ C_DocNoList.DelimitedText := FC_DocNoList;
+ ct := 0;
+ for i := 0 to C_DocNoList.Count - 1 do
+ begin
+ if C_DocNoList.Strings[i] = Docno then
+ begin
+ inc(ct);
+ end;
+ end;
+ Result := ct;
+ finally
+ C_DocNoList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CaseDelete_Enable(CaseID:String):Boolean; //案件可否被刪除
+var
+ i : Integer;
+ CaseDocNoList : TStringlist;
+begin
+ Result := True;
+ CaseDocNoList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ CaseDocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ for i := 0 to CaseDocNoList.Count - 1 do
+ begin
+ if GetUseCase('T',DisplayPath,CaseDocNoList.Strings[i]) <> '' then //有被引用走的
+ Result := False;
+ end;
+
+ finally
+ CaseDocNoList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetUseCase(Mode:Char;Path,DocDir,FormCaseID,ToCaseID:String); //記錄引用其他案件 A:加入 D:刪掉
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(Path+'UseCase.ini');
+ try
+ case Mode of
+ 'A':begin
+ ini.WriteString(DocDir,'FROM_CASEID',FormCaseID);
+ ini.WriteString(DocDir,'TO_CASEID',ToCaseID);
+ end;
+ 'D':begin
+ ini.EraseSection(DocDir);
+ end;
+ end;
+
+ finally
+ ini.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetUseCase(Mode:Char;Path,DocDir:String):String; //F:取被引用 To:引用
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(Path+'UseCase.ini');
+ try
+ case Mode of
+ 'F':begin
+ Result := ini.ReadString(DocDir,'FROM_CASEID','');
+ end;
+ 'T':begin
+ Result := ini.ReadString(DocDir,'TO_CASEID','');
+ end;
+ end;
+ finally
+ ini.Free;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.Case2upload(CaseID:String);
+var
+ i,n:Integer;
+ OldPath,NewPath,DocDir : String;
+ OldFile,NewFile,AttFile : String;
+ DocNoList,FileList:TStringlist;
+ iFileList,iFile_DocNoList :TStringlist;
+ iDocDirList : TStringlist;
+ iAttFileList : TStringlist;
+begin
+ DocNoList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ iFileList := TStringlist.Create;
+ iFile_DocNoList := TStringlist.Create;
+ iDocDirList := TStringlist.Create;
+ iAttFileList := TStringlist.Create;
+ try
+ OldPath := ImageSavePath+CaseID+'\';
+ NewPath := ImageSavePath+CaseID+'\Upload\';
+ if DirectoryExists(NewPath) then
+ _DelTree(NewPath);
+ str2dir(NewPath);
+ CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);
+ CopyFile(PWideChar(OldPath+'CaseDocNo_Copies.dat'),PWideChar(NewPath+'CaseDocNo_Copies.dat'),False);
+ CopyFile(PWideChar(OldPath+'CustomDocNo.ini'),PWideChar(NewPath+'CustomDocNo.ini'),False);
+ CopyFile(PWideChar(OldPath+'CaseIndex.dat'),PWideChar(NewPath+'CaseIndex.dat'),False);
+ CopyFile(PWideChar(OldPath+'In_Wh.dat'),PWideChar(NewPath+'In_Wh.dat'),False);
+ CopyFile(PWideChar(OldPath+'UseCase.ini'),PWideChar(NewPath+'UseCase.ini'),False);
+
+ if FileExists(OldPath+'CaseDocNo.dat') then
+ begin
+ DocNoList.LoadFromFile(OldPath+'CaseDocNo.dat');
+ end
+ else
+ begin
+ DocNoList.SaveToFile(OldPath+'CaseDocNo.dat');
+ CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);
+ end;
+
+ for i := 0 to DocNoList.Count-1 do
+ begin
+ DocDir := DocNoList.Strings[i];
+ OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
+
+ FileList.Clear;
+ if FileExists(OldPath+'Context.dat') then
+ begin
+ FileList.LoadFromFile(OldPath+'Context.dat');
+ for n := 0 to FileList.Count - 1 do
+ begin
+ OldFile := FileList.Strings[n];
+ NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
+ CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
+ iFileList.Add(NewFile);
+ iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
+ iDocDirList.Add(DocDir);
+ end;
+ end;
+ end;
+ if DirectoryExists(ImageSavePath+CaseID+'\Attach') then
+ begin
+ DocDir := 'Attach';
+ OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
+
+ FileList.Clear;
+ if FileExists(OldPath+'Context.dat') then
+ begin
+ FileList.LoadFromFile(OldPath+'Context.dat');
+ for n := 0 to FileList.Count - 1 do
+ begin
+ OldFile := FileList.Strings[n];
+ NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
+ CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
+ iFileList.Add(NewFile);
+ iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
+ iDocDirList.Add(DocDir);
+ end;
+ end;
+ end;
+
+ if DirectoryExists(ImageSavePath+CaseID+'\S_Attach') then
+ begin
+ DocDir := 'S_Attach';
+ OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
+
+ FileList.Clear;
+ if FileExists(OldPath+'Context.dat') then
+ begin
+ FileList.LoadFromFile(OldPath+'Context.dat');
+ for n := 0 to FileList.Count - 1 do
+ begin
+ OldFile := FileList.Strings[n];
+ NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
+ CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
+ iFileList.Add(NewFile);
+ iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
+ iDocDirList.Add(DocDir);
+ end;
+ end;
+ end;
+ OldPath := ImageSavePath+CaseID+'\';
+ if FileExists(OldPath+'AttContext.dat') then
+ begin
+ iAttFileList.LoadFromFile(OldPath+'AttContext.dat');
+ for n := 0 to iAttFileList.Count - 1 do
+ begin
+ AttFile := iAttFileList.Strings[n];
+ CopyFile(PWideChar(OldPath+AttFile),PWideChar(NewPath+AttFile),False);
+ end;
+ iAttFileList.SaveToFile(NewPath+'AttContext.dat');
+ end;
+
+
+ iFileList.SaveToFile(NewPath+'Context.dat');
+ iFile_DocNoList.SaveToFile(NewPath+'Context_DocNo.dat');
+ iDocDirList.SaveToFile(NewPath+'DocDir.dat');
+
+ finally
+ iFileList.Free;
+ iAttFileList.Free;
+ iFile_DocNoList.Free;
+ DocNoList.Free;
+ FileList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.Download2Case(SoDir,DeDir:String);
+var
+ i,n : Integer;
+ DocDir:String;
+ OldFile,NewFile,AttFile:String;
+ DocNoList,FileList : TStringlist;
+ iFileList,iFile_DocDirList :TStringlist;
+ iAttFileList :TStringlist;
+ AA,AA2,AA3,AA4:Boolean;
+begin
+
+ if (not FileExists(SoDir+'CaseDocNo.dat')) or (not FileExists(SoDir+'DocDir.dat')) then //截畫面會沒這些檔
+ begin
+//ShowMessage('產生必要的文字檔');
+ CreateCaseNeedData(SoDir); //產生必要的文字檔
+ end;
+
+ AA:=CopyFile(PWideChar(SoDir+'CaseDocNo.dat'),PWideChar(DeDir+'CaseDocNo.dat'),False);
+ AA2:=CopyFile(PWideChar(SoDir+'CaseDocNo_Copies.dat'),PWideChar(DeDir+'CaseDocNo_Copies.dat'),False);
+ AA3:=CopyFile(PWideChar(SoDir+'CustomDocNo.ini'),PWideChar(DeDir+'CustomDocNo.ini'),False);
+ AA4:=CopyFile(PWideChar(SoDir+'UseCase.ini'),PWideChar(DeDir+'UseCase.ini'),False);
+//ShowMessage(BoolToStr(AA)+#10#13+BoolToStr(AA2)+#10#13+BoolToStr(AA3)+#10#13+BoolToStr(AA4));
+ if FileExists(SoDir+'DocDir.dat') then //20170222 新加
+ begin
+ CopyFile(PWideChar(SoDir+'DocDir.dat'),PWideChar(DeDir+'DocDir.dat'),False);
+ end;
+
+
+ DocNoList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ iFileList := TStringlist.Create;
+ iFile_DocDirList := TStringlist.Create;
+ iAttFileList := TStringlist.Create;
+ try
+ //if Not FileExists(SoDir+'Context.dat') then Exit;
+ //iFileList.LoadFromFile(SoDir+'Context.dat');
+ //if iFileList.Count = 0 then Exit;
+ if FileExists(SoDir+'Context.dat') then
+ iFileList.LoadFromFile(SoDir+'Context.dat');
+ if FileExists(SoDir+'DocDir.dat') then
+ iFile_DocDirList.LoadFromFile(SoDir+'DocDir.dat');
+ if iFileList.Count <> iFile_DocDirList.Count then
+ begin
+ for i := 0 to iFileList.Count - 1 do
+ begin
+ if i > iFile_DocDirList.Count -1 then
+ begin
+ iFile_DocDirList.Add(FormCode2DocNo(FileName2FormCode(iFileList.Strings[i])));
+ end;
+ end;
+ end;
+ if FileExists(SoDir+'CaseDocNo.dat') then
+ DocNoList.LoadFromFile(SoDir+'CaseDocNo.dat');
+ if FileExists(DeDir+'CaseDocNo_Copies.dat') then
+ CaseDocNo_CopiesList.LoadFromFile(DeDir+'CaseDocNo_Copies.dat');
+ {for i := 0 to DocNoList.Count - 1 do
+ begin
+ DocDir := DocNoList.Strings[i];
+ MkDir(DeDir+DocDir);
+ end;}
+//ShowMessage('DocNoList='+DocNoList.Text);
+
+ for i := DocNoList.Count - 1 downto 0 do
+ begin
+ DocDir := DocNoList.Strings[i];
+ if not DirectoryExists(DeDir+DocDir) then
+ begin
+ MkDir(DeDir+DocDir);
+ if not FileExists(DeDir+DocDir+'\Context.dat') then
+ StringtoFile('',DeDir+DocDir+'\Context.dat');
+ end
+ else
+ begin
+//ShowMessage('GGG');
+ DocNoList.Delete(i);
+ DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
+ if i <= CaseDocNo_CopiesList.Count-1 then
+ begin
+//ShowMessage('KKKK');
+ CaseDocNo_CopiesList.Delete(i);
+ CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
+ end;
+ end;
+ end;
+ //20170221 先註解起來 因為他在補充掃瞄時好像會有顯示的問題
+
+ for i := 0 to iFileList.Count - 1 do
+ begin
+ OldFile := iFileList.Strings[i];
+ DocDir := iFile_DocDirList.Strings[i];
+ if (DocDir = 'Attach') or (DocDir = 'S_Attach') then
+ begin
+ if not DirectoryExists(DeDir+DocDir) then
+ MkDir(DeDir+DocDir);
+ end;
+
+ FileList.Clear;
+ if FileExists(DeDir+DocDir+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(DeDir+DocDir+'\Context.dat');
+ end;
+ NewFile := Add_Zoo(FileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
+ CopyFile(PWideChar(SoDir+OldFile),PWideChar(DeDir+DocDir+'\'+NewFile),False);
+ FileList.Add(NewFile);
+ FileList.SaveToFile(DeDir+DocDir+'\Context.dat');
+ end;
+
+ for i := DocNoList.Count -1 downto 0 do
+ begin
+ if (DocNoList.Strings[i] = 'Attach') or (DocNoList.Strings[i] = 'S_Attach') then
+ begin
+ DocNoList.Delete(i);
+ DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
+ end;
+ end;
+
+ {if (DocNoList.Count > 0) and ((DocNoList.Strings[DocNoList.Count-1] = 'Attach') or (DocNoList.Strings[DocNoList.Count-1] = 'S_Attach')) then
+ begin
+ DocNoList.Delete(DocNoList.Count-1);
+ DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
+ end; }
+ CaseDocNo_CopiesList.Clear;
+
+ if FileExists(DeDir+'CaseDocNo_Copies.dat') then
+ CaseDocNo_CopiesList.LoadFromFile(DeDir+'CaseDocNo_Copies.dat');
+ if DocNoList.Count > CaseDocNo_CopiesList.Count then
+ begin
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ if i > CaseDocNo_CopiesList.Count-1 then
+ begin
+ CaseDocNo_CopiesList.Add('1');
+ //CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
+ end;
+ end;
+ end;
+ CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
+ {if (not FileExists(DeDir+'CaseDocNo_Copies.dat') then
+ begin
+ CaseDocNo_CopiesList.Free;
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ CaseDocNo_CopiesList.Add('1');
+ CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
+ end;
+ end;}
+ if FileExists(SoDir+'AttContext.dat') then
+ begin
+ iAttFileList.LoadFromFile(SoDir+'AttContext.dat');
+ for i := 0 to iAttFileList.Count - 1 do
+ begin
+ AttFile := iAttFileList.Strings[i];
+ CopyFile(PWideChar(SoDir+AttFile),PWideChar(DeDir+AttFile),False);
+ end;
+ iAttFileList.SaveToFile(DeDir+'AttContext.dat');
+ end;
+
+
+ if FMode='ESCAN' then
+ begin
+ InitExistImgList(DeDir);
+ end;
+
+
+ finally
+ iFileList.Free;
+ FileList.Free;
+ DocNoList.Free;
+ iFile_DocDirList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FileName2NoQuene_Filename(FileName:String):String; //取出沒有序號的檔名
+var
+ v,v1 : Integer;
+ FName : String;
+begin
+ FName := ExtractFileName(FileName);
+ v := Pos('_',FName);
+ if v = 0 then //附件
+ v := pos('.',FName);
+ v1 := length(FName);
+ Result := Copy(FName,v,v1-v+1);
+end;
+
+Function TCB_IMGPSScanX.FileName2Index(FileName:String):Integer; //從檔名取出在ContextList的序號
+var
+ i : Integer;
+begin
+ for i := 0 to ContextList.Count - 1 do
+ begin
+ if FileName = ContextList.Strings[i] then
+ begin
+ Result := i;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FileName2NowDcoNo(FileName:String;CtList,DNList:TStrings):String; //從檔名取出歸屬的文件代號
+var
+ i : Integer;
+begin
+ for I := 0 to CTList.Count -1 do
+ begin
+ if FileName = CTList.Strings[i] then
+ begin
+ Result := DNList.Strings[i];
+ break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNo2DocName(CaseID,DocNo:String):String; //Docno轉Doc名稱
+var
+ i,v,ln : Integer;
+ CusDocNo,CusDocName : String;
+begin
+ Result := '';
+ if DocNo = AttName then
+ begin
+ Result := _Msg('未歸類');
+ end
+ Else
+ begin
+ If FindSQLData(Doc_Inf_List,'DOC_U_DESC','DOC_NO',DocNo,0,FindResult) Then
+ begin
+//ShowMessage(FindResult.Text);
+ Result := GetFindResult('DOC_U_DESC');
+ end;
+ end;
+
+ if Result = '' then //去自訂文件裡找
+ begin
+ Result := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
+ {for i := 0 to Cust_DocNoList.Count - 1 do
+ begin
+ v := Pos('_',Cust_DocNoList.Strings[i]);
+ ln := length(Cust_DocNoList.Strings[i]);
+ CusDocNo := Copy(Cust_DocNoList.Strings[i],1,v-1);
+ CusDocName := Copy(Cust_DocNoList.Strings[i],v+1,ln-v);
+ if DocNo = CusDocNo then
+ begin
+ Result := CusDocName;
+ Break;
+ end;
+ end;}
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.DocNo2FileName(DocNo:String;List:TStrings):String; //用DocNo找出檔名(第一頁)
+var
+ i : Integer;
+begin
+ Result := '';
+ for i := 0 to List.Count - 1 do
+ begin
+ IF DocNo = FormCode2DocNo(FileName2FormCode(List.Strings[i])) then
+ begin
+ Result := List.Strings[i];
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNo2WorkNo(DocNo:String):String; //用DocNo取出作業別
+begin
+ Result := '';
+ If FindSQLData(Doc_Inf_List,'WORK_NO','DOC_NO',DocNo,0,FindResult) Then
+ begin
+ Result := GetFindResult('WORK_NO');
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNoNeedDiv(DocNo:String):Boolean; //是否是需分份數的文件代號
+var
+ NeedDiv : String;
+begin
+ Result := False;
+ If FindSQLData(Doc_Inf_List,'IS_DOC_DIV','DOC_NO',DocNo,0,FindResult) Then
+ begin
+ NeedDiv := GetFindResult('IS_DOC_DIV');
+ if NeedDiv = 'Y' then
+ Result := True;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocnoNeedGroup(DocNo:String):Boolean; //傳入的DocNo是否需分組
+begin
+ Result := False;
+ If FindSQLData(Doc_Inf_List,'IS_DOC_DIV','DOC_NO',DocNo,0,FindResult) Then
+ begin
+ if GetFindResult('IS_DOC_DIV') = 'Y' Then
+ Result := True;
+ end;
+end;
+
+Function TCB_IMGPSScanX.OMRCheckCase(CaseID:String):Boolean; //OMR檢核
+var
+ i,n,m,v,v1 : Integer;
+ XT,RelaXT,ValueXT : TXmltool;
+ OMRFormCode,OMRFile,OMRFormName,ColEName,ColCName,Site : String;
+ Pixel : Integer;
+ RelaFormCode,RelaFile,RelaFormName,RelaColEName,RelaColCName,RelaSite : String;
+ RelaDocNo,RelaDocName : string;
+ RelaPixel : Integer;
+ s : String;
+ nodename : String;
+ OMROK : Boolean;
+ CaseOk : Boolean;
+ ErrStr : String;
+ SiteRec,RelaSiteRec : String; //多組位置記錄
+ OMRValue : String;
+ MainFormID,MainDocNo,MainVersion : String; //主FormID
+ MainFormPage,CaseFormPage : Integer; //主要文件需要的頁數
+ NeedDocNoStr,NoDocNoStr : String; //相依 互斥文件字串
+ List : TStringlist;
+ FormCode : String;
+ FormDataPages : Integer;
+ NoSite : Boolean; //未定位
+ Anchor,Anchor1 : String;
+ OMROkCount : Integer;
+ //Casecheck : Boolean; //是否要做檢核
+ //AllCheck : Boolean; //是否要做完整檢核
+
+ ISB8W,ISB8H:integer;
+begin
+ ///OMRErrInfo 1: 必要文件 2:相依文件 3:互斥文件 4:必填 5:欄位有值附文件 6:欄位有值不附文件
+ /// 7: 欄位有值相關欄位也要有值 8:欄位有值要寫備註 9:停用日期 10:最大頁數
+ //Casecheck := True;
+ //Allcheck := True;
+ //if (FMode = 'ISCAN') then
+ //Allcheck := False;
+ CaseOk := True;
+ //if Casecheck then
+ //begin
+ DeleteFile(ImageSavePath+CaseID+'\upload\Checkerr.ini');
+ DeleteFile(ImageSavePath+CaseID+'\upload\CheckMemo.dat');
+ //DeleteFile(ImageSavePath+CaseID+'\upload\ReSize.dat');
+ DeleteFile(ImageSavePath+CaseID+'\upload\RemoveMemo.dat');
+ DeleteFile(ImageSavePath+CaseID+'\upload\OMRCheckOk.dat');
+ Memo1.Lines.Clear;
+ OMRFileList.Clear;
+
+ MainFormID := GetCaseFormID(ImageSavePath+CaseID+'\upload\');
+ List := TStringlist.Create;
+ try
+ //if AllCheck then
+ //begin
+ if GetCasePage(ImageSavePath,CaseID) =0 then
+ begin
+
+ end;
+//ShowMessage('MainFormID='+MainFormID);
+LogFile1.LogToFile(logTimeString+' '+FModeName+' '+CaseID+' '+'MainFormID='+MainFormID);
+ if MainFormID = ''then
+ begin
+ //20131203 yuu說不檢查這個,先拿掉 20170315 楷琳說未歸類要擋 20170726 因此有檢查必要FormID 所以 可以拿掉
+ {if FCheck_main_form='Y' then
+ begin
+ if (FMode <> 'SSCAN') AND (FMode<>'ESCAN') then //簽署章件會換主FormID,先跳過 20170629 ESCAN 也不檢查
+ begin
+ ErrStr:=_Msg('找不到分案文件'); //找不到主文件
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,False,True);
+ CaseOk := false;
+//ShowMessage('AAAAA');
+ end;
+ end;
+ }
+ end
+ Else
+ begin
+ //////主要非主要文件//////
+ DistinctDocinCase(ImageSavePath+CaseID+'\upload\');
+//ShowMessage(DocNo_VerinCase.Text);
+//DocNo_VerinCase.Add('31A00101_1706A');
+LogFile1.LogToFile(logTimeString+' '+CaseID+' '+'DocNo_VerinCase.Text='+DocNo_VerinCase.Text);
+ if ModeNeedCheck(OMRErrInfo[1].Mode,FMode) then //是否要檢核
+ begin
+ for i := 0 to DocNo_VerinCase.Count - 1 do
+ begin
+ v := Pos('_', DocNo_VerinCase.Strings[i]);
+ v1 := length(DocNo_VerinCase.Strings[i]);
+ MainDocNo := Copy(DocNo_VerinCase.Strings[i],1,v-1); //FormCode2DocNo(MainFormID);
+ MainVersion :=Copy(DocNo_VerinCase.Strings[i],v+1,v1-v); //FormCode2Version(MainFormID);
+ MainFormPage := GetDataDocNoPage(MainDocNo,MainVersion); //資料庫記錄主文件頁數
+ CaseFormPage := CheckCaseDocNoPage(CaseID,MainDocNo,MainVersion,MainFormPage); //案件主文件的頁數
+LogFile1.LogToFile(logTimeString+CaseID+',MainDocNo='+MainDocNo+',MainVersion='+MainVersion+',MainFormPage='+IntToStr(MainFormPage)+',CaseFormPage='+IntToStr(CaseFormPage));
+ //CheckFirstDocNoPage
+ IF (MainFormPage > 0) and (MainFormPage <> CaseFormPage) then
+ begin
+ ErrStr:=MainDocNo+Format(OMRErrInfo[1].Info,[Inttostr(MainFormPage),Inttostr(CaseFormPage)]); //主要文件需有XX頁僅附XX頁
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[1].Ignore,OMRErrInfo[1].Display);
+ if OMRErrInfo[1].Display then
+ CaseOk := false;
+ end;
+ end;
+ end;
+ //////主要非主要文件/////
+//showmessage(MainFormID);
+ MainDocNo := FormCode2DocNo(MainFormID);
+ MainVersion := FormCode2Version(MainFormID);
+ if FindSQLData(DM_FORM_INF_List,'DEPE_FORM_ID,MUTEX_FORM_ID','MAIN_FORM_ID,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) then
+ begin
+ NeedDocNoStr := GetFindResult('DEPE_FORM_ID');
+ NoDocNoStr := GetFindResult('MUTEX_FORM_ID');
+ end
+ Else if FindSQLData(DM_FORM_INF_List,'DEPE_FORM_ID,MUTEX_FORM_ID','MAIN_FORM_ID,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) then
+ begin
+ NeedDocNoStr := GetFindResult('DEPE_FORM_ID');
+ NoDocNoStr := GetFindResult('MUTEX_FORM_ID');
+ end;
+
+ //////相依文件/////
+ if ModeNeedCheck(OMRErrInfo[2].Mode,FMode) then //是否要檢核
+ begin
+ List.CommaText := NeedDocNoStr;
+ for I := 0 to List.Count - 1 do
+ begin
+ if not Case_DocNoExists(CaseID,List.Strings[i]) then //沒附相依文件
+ begin
+ if FWH_category='N' then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\upload\'+List.Strings[i]) then
+ begin
+ Continue;
+ end;
+ end;
+ ErrStr:=Format(OMRErrInfo[2].Info,[DocNo2DocName(CaseID,List.Strings[i])]); //沒附相依文件
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[2].Ignore,OMRErrInfo[2].Display);
+ if OMRErrInfo[2].Display then
+ CaseOk := false;
+ end;
+ end;
+ end;
+ //////相依文件/////
+
+ //////互斥文件/////
+ if ModeNeedCheck(OMRErrInfo[3].Mode,FMode) then //是否要檢核
+ begin
+ List.CommaText := NoDocNoStr;
+ for I := 0 to List.Count - 1 do
+ begin
+ if Case_DocNoExists(CaseID,List.Strings[i]) then //附了互斥文件
+ begin
+ if FWH_category='N' then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\upload\'+List.Strings[i]) then
+ begin
+ Continue;
+ end;
+ end;
+ ErrStr:=Format(OMRErrInfo[3].Info,[DocNo2DocName(CaseID,List.Strings[i])]); //有附互斥文件
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[3].Ignore,OMRErrInfo[3].Display);
+ if OMRErrInfo[3].Display then
+ CaseOk := false;
+ end;
+ end;
+ end;
+ //////互斥文件/////
+ end; //MainFormID結束
+ //end;
+ List.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
+ for i := 0 to List.Count - 1 do
+ begin
+ FormCode := FileName2FormCode(List.Strings[i]);
+ /////未歸類///
+ {IF FormCode = 'Attach' Then //20140211 yuu說不檢查了
+ begin
+ ErrStr:=_Msg('尚有文件未歸類');
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,False,True);
+ CaseOk := false;
+ end; }
+ /////未歸類//////
+
+ /////未註冊文件/////
+ {IF not FormIDExists(FormCode,False) then //未註冊文件
+ begin
+ ErrStr:=FormCode+_Msg('不為此業務的表單代碼');
+ OMRErr2ini(CaseID,ErrStr,'','','','',False,False,True);
+ CaseOk := false;
+ end }
+ /////未註冊文件/////
+ //////停用文件//
+ {Else} IF ModeNeedCheck(OMRErrInfo[9].Mode,FMode) and (not FormIDExists(FormCode,True,0)) and (not checkFormCodeIsCustom(ImageSavePath + CaseID+'\upload\',FormCode)) then //有停用的文件
+ begin
+//ShowMessage('AAAA');
+ ErrStr:=Format(OMRErrInfo[9].Info,[FormCode2FormName(CaseID,FormCode)]); //有停用文件
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[9].Ignore,OMRErrInfo[9].Display);
+//ShowMessage('ErrStr='+ErrStr);
+ if OMRErrInfo[9].Display then
+ CaseOk := false;
+ end;
+ //////停用文件////
+ end;
+ finally
+ List.Free;
+ end;
+ //if AllCheck then
+ //begin
+ //////最大頁數///
+LogFile1.LogToFile(logTimeString+'最大頁數A段 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
+ DistinctFormCode(CaseID);
+ if ModeNeedCheck(OMRErrInfo[10].Mode,FMode) then //是否要檢核
+ begin
+//ShowMessage('AAA'+OMRFileList.Text);
+LogFile1.LogToFile(logTimeString+'最大頁數B段 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
+ For i := 0 to OMRFileList.Count - 1 do
+ begin
+ if FModeName=_Msg('異動件') then Continue;
+
+ if FWH_category='N' then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\upload\'+OMRFileList.Strings[i]) then
+ begin
+ Continue;
+ end;
+ end;
+ FormCode := FileName2FormCode(OMRFileList.Strings[i]);
+ FormDataPages := GetDataFormCodePages(FormCode);
+
+ IF (FormCode <> '') and (FormDataPages > 0) and (FindFormCodePages(CaseID,FormCode) > FormDataPages) then //有超過最大頁數的文件
+ begin
+ ErrStr:=Format(OMRErrInfo[10].Info,[FormCode2FormName(CaseID,FormCode),inttostr(FormDataPages)]); //有超過最大頁數文件
+ OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[10].Ignore,OMRErrInfo[10].Display);
+ if OMRErrInfo[10].Display then
+ CaseOk := false;
+ end;
+ end;
+ end;
+ /////最大頁數/////
+ //end;
+ ImageScrollBox1.FileName := '';
+ //if FWork_No = 'CW' then //理賠就不做下面的檢核了
+ //begin
+ //////OMR檢核///////
+ ContextList.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
+ DistinctFormCode(CaseID);
+ ValueXT := TXmltool.Create;
+ Try
+//ShowMessage('必填'+OMRFileList.Text);
+LogFile1.LogToFile(logTimeString+'必填 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
+ For i := 0 to OMRFileList.Count - 1 do
+ begin
+//ShowMessage('OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
+ if CheckRequiredColumnValues(FWork_NO,CaseID) then Continue;
+
+ OMRFile := OMRFileList.Strings[i];
+ OMRFormCode := FileName2FormCode(OMRFileList.Strings[i]);
+ OMRFormName := FormCode2FormName(CaseID,OMRFormCode);
+ Anchor := FormID2Anchor(OMRFormCode);
+ ///依十字定位點縮放////
+ ImageReSize_FormID(CaseID,OMRFile);
+ ////依十字定位點縮放///
+//Display1.Lines.Add('OMRFile='+OMRFile+',OMRFormCode='+OMRFormCode+',OMRFormName='+OMRFormName);
+LogFile1.LogToFile(logTimeString+'OMRFile='+OMRFile+',OMRFormCode='+OMRFormCode+',OMRFormName='+OMRFormName);
+//ShowMessage('KKKKK');
+ if not FileExists(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml') then //沒有Xml就不用檢核
+ Continue;
+
+//ShowMessage('11638 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
+ XT := TXmltool.Create(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml');
+ RelaXT := TXmltool.Create;
+//ShowMessage('ModeNeedCheck='+BoolToStr(ModeNeedCheck(OMRErrInfo[4].Mode,FMode),true));
+ try
+ //*******必填********
+ if ModeNeedCheck(OMRErrInfo[4].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype1/'].First then
+ Repeat
+ OMROK := False;
+ SiteRec := ''; //清掉
+ ColEName := XT.SubNodes['/form/settype1/'].NodeName;
+ ColCName := XT.Node['/form/settype1/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ if XT.SubNodes['/form/settype1/'+ColEName+'/'].First then
+ Repeat
+ nodename := XT.SubNodes['/form/settype1/'+ColEName+'/'].NodeName;
+ If nodename <> '@coldesc' then
+ begin
+ Pixel := Strtoint(XT.Node['/form/settype1/'+ColEName+'/'+nodename+'/'].Attributes['pixel']);
+ Site := XT.Node['/form/settype1/'+ColEName+'/'+nodename+'/'].Attributes['colxy'];
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+ //有填就ok
+ //Showmessage(ColCName +','+ inttostr(OMRMpsV1.GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site))+','+inttostr(Pixel + SafePixel));
+//SafePixel:=90000;
+Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+//FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,ANCHOR);
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ //Showmessage('oh');
+ OMROK := True;
+ Break;
+ end;
+ end
+ Else
+ begin
+ //ColCName := XT['/form/settype1/'+ColEName+'/'+nodename+'/'];
+ end;
+ Until not XT.SubNodes['/form/settype1/'+ColEName+'/'].Next;
+ if not OMROk then
+ begin
+ ErrStr:=Format(OMRErrInfo[4].Info,[ColCName]); //XX欄位未填寫
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[4].Ignore,OMRErrInfo[4].Display);
+ if OMRErrInfo[4].Display then
+ CaseOk := false;
+ end;
+ Until not XT.SubNodes['/form/settype1/'].Next ;
+ end;
+ //*******必填********
+//ShowMessage('11692 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
+ //if AllCheck then
+ //begin
+ //*******有值相關文件的欄位也要有值*******
+ if ModeNeedCheck(OMRErrInfo[7].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype3/'].First then
+ Repeat
+ SiteRec := '';
+ RelaSiteRec := '';
+ ColEName := XT.SubNodes['/form/settype3/'].NodeName;
+ ColCName := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ Site := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['colxy'];
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+ Pixel := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['pixel'];
+Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ////有填寫////
+
+ if XT.SubNodes['/form/settype3/'+ColEName+'/'].First then
+ Repeat
+ RelaSiteRec := '';
+ nodename := XT.SubNodes['/form/settype3/'+ColEName+'/'].NodeName;
+ If (nodename <> '@coldesc') and (not XT.SubNodes['/form/settype3/'+ColEName+'/'].NodeIsAttr) then
+ begin
+ RelaFormCode := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaColEName := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['rela_col_name'];
+ RelaColCName := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['relacoldesc'];
+ RelaColCName := Copy(RelaColCName,1,length(RelaColCName)-6);
+ RelaFile := FormCode2FileName(RelaFormCode,ContextList);
+ RelaFormName := FormCode2FormName(CaseID,RelaFormCode);
+ Anchor1 := FormID2Anchor(RelaFormCode);
+ RelaXT.LoadFromFile(CheckXmlPath+FWork_no+'\'+RelaFormCode+'.xml');
+Display1.Lines.Add(RelaFile+','+RelaFormName);
+//ShowMessage(RelaFile);
+//ShowMessage(ImageSavePath+CaseID+'\upload\'+RelaFile);
+ if RelaFile<>'' then
+ begin
+ ISB8.LoadFromFile(ImageSavePath+CaseID+'\upload\'+RelaFile,1); //20170815
+ ISB8W:= ISB8.Graphic.Width;
+ ISB8H:= ISB8.Graphic.Height;
+ FindPoint(ISB8.Graphic,UpLPoint,UpRPoint,DownLPoint,ISB8W,ISB8H,ANCHOR); //20170815 抓相關然欄位所在圖檔的定位
+ end;
+
+ OMROK := False;
+ //OMROK := False;
+ //if RelaXT.SubNodes['/form/settype2/'].First then
+ //Repeat
+ NoSite := True;
+ if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Count >0 then
+ NoSite := False;
+ if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].First then
+ Repeat
+ nodename := RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].NodeName;
+ If nodename <> '@coldesc' then
+ begin
+ RelaPixel := Strtoint(RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['pixel']);
+ RelaSite := RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['colxy'];
+ if RelaSiteRec= '' then //記錄位置
+ RelaSiteRec := RelaSite
+ else
+ RelaSiteRec := RelaSiteRec+'@'+RelaSite;
+ if FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
+ begin
+Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSite,Bt) > (RelaPixel + SafePixel) then
+ begin
+ OMROK := True;
+ Break;
+ end;
+ ///依十字定位點縮放////
+ ImageReSize_FormID(CaseID,OMRFile); //20170815 重新抓定位
+ ////依十字定位點縮放////
+ end;
+ end;
+
+ Until not RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Next;
+ if not OMROk then
+ begin
+ if not FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
+ ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName])+'('+_msg('未附')+RelaFormName+')' //XX欄位填寫時,XX欄位未填寫
+ Else if NoSite then
+ ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName])+'('+_msg('未定位')+')'
+ Else
+ ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName]); //XX欄位填寫時,XX欄位未填寫
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSiteRec,Anchor,Anchor1,False,OMRErrInfo[7].Ignore,OMRErrInfo[7].Display);
+ if OMRErrInfo[7].Display then
+ CaseOk := false;
+ end;
+ //Until not RelaXT.SubNodes['/form/settype2/'].Next ;
+
+ end;
+ Until not XT.SubNodes['/form/settype3/'+ColEName+'/'].Next;
+ end;
+ Until not XT.SubNodes['/form/settype3/'].Next ;
+ end;
+ //*******有值相關文件的欄位也要有值*******
+//ShowMessage('11788 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
+
+ //*******有值相關文件的欄位不能有值*******
+ if ModeNeedCheck(OMRErrInfo[11].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype8/'].First then
+ Repeat
+ SiteRec := '';
+ RelaSiteRec := '';
+ OMROkCount := 0;
+ ColEName := XT.SubNodes['/form/settype8/'].NodeName;
+ ColCName := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ Site := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['colxy'];
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+ Pixel := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['pixel'];
+Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ////有填寫// //
+ inc(OMROkCount);
+ end;
+ if XT.SubNodes['/form/settype8/'+ColEName+'/'].First then
+ Repeat
+ RelaSiteRec := '';
+ nodename := XT.SubNodes['/form/settype8/'+ColEName+'/'].NodeName;
+ If (nodename <> '@coldesc') and (not XT.SubNodes['/form/settype8/'+ColEName+'/'].NodeIsAttr) then
+ begin
+ RelaFormCode := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaColEName := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['rela_col_name'];
+ RelaColCName := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['relacoldesc'];
+ RelaColCName := Copy(RelaColCName,1,length(RelaColCName)-6);
+ RelaFile := FormCode2FileName(RelaFormCode,ContextList);
+ RelaFormName := FormCode2FormName(CaseID,RelaFormCode);
+ Anchor1 := FormID2Anchor(RelaFormCode);
+ RelaXT.LoadFromFile(CheckXmlPath+FWork_no+'\'+RelaFormCode+'.xml');
+
+ if RelaFile<>'' then
+ begin
+ ISB8.LoadFromFile(ImageSavePath+CaseID+'\upload\'+RelaFile,1); //20170815
+ ISB8W:= ISB8.Graphic.Width;
+ ISB8H:= ISB8.Graphic.Height;
+ FindPoint(ISB8.Graphic,UpLPoint,UpRPoint,DownLPoint,ISB8W,ISB8H,ANCHOR); //20170815 抓相關然欄位所在圖檔的定位
+ end;
+
+ OMROK := False;
+ //OMROK := False;
+ //if RelaXT.SubNodes['/form/settype2/'].First then
+ //Repeat
+ NoSite := True;
+ if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Count >0 then
+ NoSite := False;
+ if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].First then
+ Repeat
+ nodename := RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].NodeName;
+ If nodename <> '@coldesc' then
+ begin
+ RelaPixel := Strtoint(RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['pixel']);
+ RelaSite := RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['colxy'];
+ if RelaSiteRec= '' then //記錄位置
+ RelaSiteRec := RelaSite
+ else
+ RelaSiteRec := RelaSiteRec+'@'+RelaSite;
+ if FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
+ begin
+Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSite,Bt) > (RelaPixel + SafePixel) then
+ begin
+ inc(OMROkCount);
+ //OMROK := True;
+ //Break;
+ end;
+ ///依十字定位點縮放////
+ ImageReSize_FormID(CaseID,OMRFile);
+ ////依十字定位點縮放////
+ end;
+ end;
+ //Else
+ //begin
+ //ColCName := XT['/form/settype1/'+ColEName+'/'+nodename+'/'];
+ //end;
+ Until not RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Next;
+ if OMROkCount > 1 then
+ begin
+ if not FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
+ ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName])+'('+_msg('未附')+RelaFormName+')' //XX欄位填寫時,XX欄位也填寫
+ Else if NoSite then
+ ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName])+'('+_msg('未定位')+')'
+ Else
+ ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName]); //XX欄位填寫時,XX欄位也填寫
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSiteRec,Anchor,Anchor1,False,OMRErrInfo[7].Ignore,OMRErrInfo[7].Display);
+ if OMRErrInfo[11].Display then
+ CaseOk := false;
+ end;
+ //Until not RelaXT.SubNodes['/form/settype2/'].Next ;
+
+ end;
+ Until not XT.SubNodes['/form/settype8/'+ColEName+'/'].Next;
+ Until not XT.SubNodes['/form/settype8/'].Next ;
+ end;
+ //*******有值相關文件的欄位不能有值*******
+
+//ShowMessage('11889 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
+
+ //*******有值相依文件*******
+ if ModeNeedCheck(OMRErrInfo[5].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype4/'].First then
+ Repeat
+ SiteRec := '';
+ RelaSiteRec := '';
+ ColEName := XT.SubNodes['/form/settype4/'].NodeName;
+ ColCName := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ Site := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['colxy'];
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+ Pixel := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['pixel'];
+ Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ////有填寫////
+ if XT.SubNodes['/form/settype4/'+ColEName+'/'].First then
+ Repeat
+ nodename := XT.SubNodes['/form/settype4/'+ColEName+'/'].NodeName;
+ If (nodename <> 'coldesc') and (not XT.SubNodes['/form/settype4/'+ColEName+'/'].NodeIsAttr) then
+ begin
+ {RelaFormCode := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaFile := FormCode2FileName(RelaFormCode);
+ RelaFormName := FormCode2FormName(RelaFormCode); }
+ RelaDocNo := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaFile := DocNo2FileName(RelaDocNo,ContextList);
+ RelaDocName := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformname'];
+ if RelaFile='' then
+ begin
+ ErrStr:=Format(OMRErrInfo[5].Info,[ColCName,RelaDocName]); //XX文件XX欄位填寫時,需附XX文件
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[5].Ignore,OMRErrInfo[5].Display);
+ if OMRErrInfo[5].Display then
+ CaseOk := false;
+ end;
+ end;
+ Until not XT.SubNodes['/form/settype4/'+ColEName+'/'].Next;
+ end;
+ Until not XT.SubNodes['/form/settype4/'].Next ;
+ end;
+ //*******有值相依文件*******
+
+ //*******有值互斥文件*******
+ if ModeNeedCheck(OMRErrInfo[6].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype5/'].First then
+ Repeat
+ SiteRec := '';
+ RelaSiteRec := '';
+ ColEName := XT.SubNodes['/form/settype5/'].NodeName;
+ ColCName := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ Site := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['colxy'];
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+ Pixel := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['pixel'];
+ Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ////有填寫////
+ if XT.SubNodes['/form/settype5/'+ColEName+'/'].First then
+ Repeat
+ nodename := XT.SubNodes['/form/settype5/'+ColEName+'/'].NodeName;
+ If (nodename <> 'coldesc') and (not XT.SubNodes['/form/settype5/'+ColEName+'/'].NodeIsAttr) then
+ begin
+ {RelaFormCode := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaFile := FormCode2FileName(RelaFormCode);
+ RelaFormName := FormCode2FormName(RelaFormCode);}
+ RelaDocNo := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
+ RelaFile := DocNo2FileName(RelaDocNo,ContextList);
+ RelaDocName := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformname'];
+ if RelaFile<>'' then //有附 20130604看到(='')改的(未測)
+ begin
+ ErrStr:=Format(OMRErrInfo[6].Info,[ColCName,RelaDocName]); //XX文件XX欄位填寫時,不能附XX文件
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[6].Ignore,OMRErrInfo[6].Display);
+ if OMRErrInfo[6].Display then
+ CaseOk := false;
+ end;
+ end;
+ Until not XT.SubNodes['/form/settype5/'+ColEName+'/'].Next;
+ end;
+ Until not XT.SubNodes['/form/settype5/'].Next ;
+ end;
+ //*******有值互斥文件*******
+
+ //*******有值寫備註*******
+ if ModeNeedCheck(OMRErrInfo[8].Mode,FMode) then //是否要檢核
+ begin
+ if XT.SubNodes['/form/settype6/'].First then
+ Repeat
+ SiteRec := '';
+ ColEName := XT.SubNodes['/form/settype6/'].NodeName;
+ ColCName := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['coldesc'];
+ ColCName := Copy(ColCName,1,length(ColCName)-6);
+ Site := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['colxy'];
+ Pixel := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['pixel'];
+
+ if SiteRec= '' then //記錄位置
+ SiteRec := Site
+ else
+ SiteRec := SiteRec+'@'+Site;
+
+ Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ////有填寫////
+ if not FileExists(ImageSavePath+CaseID+'ScanMemo.dat') then
+ begin
+ ErrStr:=Format(OMRErrInfo[8].Info,[ColCName]); //XX文件XX欄位填寫時,需寫備註
+ OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[8].Ignore,OMRErrInfo[8].Display);
+ if OMRErrInfo[8].Display then
+ CaseOk := false;
+ end;
+ end;
+ Until not XT.SubNodes['/form/settype6/'].Next ;
+ end;
+ //*******有值寫備註*******
+
+ //*******OMR帶值********
+ if XT.SubNodes['/form/settype7/'].First then
+ Repeat
+ ColEName := XT.SubNodes['/form/settype7/'].NodeName;
+ ValueXT['/content/'+ColEName+'/@savevalue'] := ''; //先給預設空白
+ if XT.SubNodes['/form/settype7/'+ColEName+'/'].First then
+ Repeat
+ nodename := XT.SubNodes['/form/settype7/'+ColEName+'/'].NodeName;
+ If nodename <> '@coldesc' then
+ begin
+ Pixel := Strtoint(XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['pixel']);
+ Site := XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['colxy'];
+ OMRValue := XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['getvalue'];
+
+ //有填就ok
+ Display1.Lines.Add(ColEName+' '+ColCName+' 圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
+
+ if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
+ begin
+ ValueXT['/content/'+ColEName+'/@savevalue'] := OMRValue; //有填就換成設定的值
+ Break;
+ end;
+ end;
+ Until not XT.SubNodes['/form/settype7/'+ColEName+'/'].Next;
+ Until not XT.SubNodes['/form/settype7/'].Next ;
+
+ //*******OMR帶值********
+ //end;
+ Finally
+ if (OMRValue <> '') then
+ ValueXT.SaveToFile(ImageSavePath+CaseID+'/GetValue.xml');
+ XT.Free;
+ RelaXT.Free;
+ end;
+ end;
+ //必填迴圈結束
+ Finally
+ ValueXT.Free;
+ end;
+ //end;
+ //end;
+ Result := CaseOk;
+end;
+
+function TCB_IMGPSScanX.OMRErrini2ListForLog(CaseID: String): String;
+var
+ ini : Tinifile;
+ Errcount : Integer;
+ Del : Boolean;
+ i,j : Integer;
+ ST,CaseList:TStringList;
+
+begin
+ Result:='';
+ //CaseList.dat
+ ST:=TStringList.Create;
+ CaseList:=TStringList.Create;
+ CaseList.LoadFromFile(ImageSavePath+'CaseList.dat');
+ for I := 0 to CaseList.Count - 1 do
+ begin
+ ini := Tinifile.Create(ImageSavePath + CaseList.Strings[i]+'\upload\Checkerr.ini');
+ try
+ Errcount := ini.ReadInteger('OMRCount','Count',0);
+
+ for j := 1 to ErrCount do
+ begin
+ Del := ini.ReadBool(inttostr(j),'Del',False); //是否被移除了
+ if Not Del then
+ begin
+ ST.Add(ini.ReadString(inttostr(j),'Reason','')) ;
+ end;
+ end;
+ finally
+ ini.Free;
+ end;
+ end;
+ Result:=ST.Text;
+ ST.Free;
+ CaseList.Free;
+end;
+
+
+Procedure TCB_IMGPSScanX.CreateDocNo_DocName(Path,CaseID:String); //產生DocNo_DocName.dat
+var
+ i : Integer;
+ S : TStringlist;
+ Doc_Name : String;
+begin
+ S := TStringlist.Create;
+ try
+ DistinctDocNoinCase(Path);
+ for i := 0 to CaseDocNoList.Count - 1 do
+ begin
+ Doc_Name := CaseDocNoList.Strings[i]+'_'+DocNo2DocName(CaseID,CaseDocNoList.Strings[i]);
+ if not DocnoNeedGroup(CaseDocNoList.Strings[i]) Then //不用分組的加*號給智豪
+ Doc_Name := '*'+Doc_Name;
+ S.Add(Doc_Name);
+ end;
+ S.SaveToFile(Path+'DocNo_Name.dat',TEnCoding.UTF8);
+ finally
+ S.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CreateDocNo_Info(CaseID:String):String; //產生 DocNo[tab]份數[tab]總頁數[tab]是否異動[換行]DocNo[tab]份數[tab]總頁數[tab]是否異動
+var
+ i,n : Integer;
+ DocDirList,DocDir_CopiesList,FileList,C_DocNoList : TStringlist;
+ DocNo,iDocDir,iDocNo,iEdit:String;
+ icopys,ipages : integer;
+ S,S1 : TStringlist;
+ Str : String;
+begin
+ DocDirList := TStringlist.Create;
+ DocDir_CopiesList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ C_DocNoList := TStringlist.Create;
+ try
+ Str := '';
+ if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
+
+ DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+
+ if DocDirList.Count =0 then exit;//20170222 新加
+
+
+ DocDir_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ while DocDirList.Count > 0 do
+ begin
+ iDocDir := DocDirList.Strings[0];
+ DocNo := DocNoDir2DocNo(iDocDir);
+ if Copy(iDocDir,1,5) <> 'ZZZZZ' then //不為自定文件
+ begin
+ //icopys := 1;
+ icopys := GetDocNoCount(CaseID,DocNo);
+ ipages := GetDocDir_Page(CaseID,iDocDir);
+ iEdit := GetDocNoEdit(CaseID,DocNo,'');
+ for i := DocDirList.Count - 1 downto 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocNo := DocNoDir2DocNo(iDocDir);
+ if iDocNo = DocNo then
+ begin
+ //inc(icopys);
+ ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
+ DocDirList.Delete(i);
+ end;
+ end;
+ if str = '' then
+ Str := Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocNo,iCopys,iPages,iEdit])
+ else
+ Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocNo,iCopys,iPages,iEdit]);
+ end;
+ DocDirList.Delete(0);
+ end;
+
+
+ finally
+ DocDirList.Free;
+ DocDir_CopiesList.Free;
+ FileList.Free;
+ C_DocNoList.Free;
+ end;
+ Result := Str;
+
+ {S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ S.LoadFromFile(Path+'Context.dat');
+ S1.LoadFromFile(Path+'Context_DocNo.dat');
+ for i := 0 to CaseDocNoList.Count - 1 do
+ begin
+ iDocNo := CaseDocNoList.Strings[i];
+ iCopys := GetDocNo_Count(Path,iDocNo);
+ iPages := GetDocNo_Page(Path,iDocNo);
+ if str = '' then
+ Str := Format('%s,%d,%d',[iDocNo,iCopys,iPages])
+ else
+ Str := Str+';'+ Format('%s,%d,%d',[iDocNo,iCopys,iPages]);
+ end;
+ Result := Str;
+
+ finally
+ S.Free;
+ S1.Free;
+ end; }
+end;
+
+Function TCB_IMGPSScanX.CreateCustDocNo_Info(CaseID:String):String; //產生自訂文件 DocName[tab]份數[tab]總頁數[tab]是否異動[#13#10]DocName[tab]份數[tab]總頁數[tab]是否異動
+var
+ i,n : Integer;
+ DocDirList,FileList : TStringlist;
+ DocNo,DocName,iDocDir,iDocNo,iEdit:String;
+ icopys,ipages : integer;
+ S,S1 : TStringlist;
+ Str : String;
+begin
+ DocDirList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ Str := '';
+ if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
+ DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+//ShowMessage(DocDirList.Text);
+ while DocDirList.Count > 0 do
+ begin
+ iDocDir := DocDirList.Strings[0];
+ DocNo := DocNoDir2DocNo(iDocDir);
+ if Copy(iDocDir,1,5) = 'ZZZZZ' then //是自定文件
+ begin
+ //icopys := 1;
+ DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
+ icopys := GetDocNoCount(CaseID,DocNo);
+ ipages := GetDocDir_Page(CaseID,iDocDir);
+ iEdit := GetDocNoEdit(CaseID,DocNo,DocName);
+ for i := DocDirList.Count - 1 downto 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocNo := DocNoDir2DocNo(iDocDir);
+ if iDocNo = DocNo then
+ begin
+ //inc(icopys);
+ ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
+ DocDirList.Delete(i);
+ end;
+ end;
+ DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
+ if str = '' then
+ Str := Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocName,iCopys,iPages,iEdit])
+ else
+ Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocName,iCopys,iPages,iEdit]);
+ end;
+ DocDirList.Delete(0);
+ end;
+ finally
+ DocDirList.Free;
+ FileList.Free;
+ end;
+ Result := Str;
+end;
+
+Function TCB_IMGPSScanX.CreateDocnoFrom_Info(CaseID:String):String; //產生被引進的保管袋文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+var
+ i,n : Integer;
+ DocDirList,DocDir_CopiesList,FileList : TStringlist;
+ DocNo,iDocDir,iDocNo,iEdit:String;
+ FromCaseID : string;
+ icopys,ipages : integer;
+ S,S1 : TStringlist;
+ Str : String;
+begin
+ DocDirList := TStringlist.Create;
+ DocDir_CopiesList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ Str := '';
+ if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
+ DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+
+ if DocDirList.Count=0 then exit;//20170222 新加
+
+
+ DocDir_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
+ while DocDirList.Count > 0 do
+ begin
+ iDocDir := DocDirList.Strings[0];
+ DocNo := DocNoDir2DocNo(iDocDir);
+ if (Copy(iDocDir,1,5) <> 'ZZZZZ') then //不為自定文件
+ begin
+ //icopys := 1;
+ //icopys := GetDocNoCount(CaseID,DocNo);
+ icopys := GetDocDirCopies(CaseID,iDocDir);
+ ipages := GetDocDir_Page(CaseID,iDocDir);
+ iEdit := GetDocNoEdit(CaseID,DocNo,'');
+ FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
+ if FromCaseID <> '' then
+ begin
+ for i := DocDirList.Count - 1 downto 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocNo := DocNoDir2DocNo(iDocDir);
+ if (iDocNo = DocNo) and (GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir)<>'') then
+ begin
+ FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
+ //inc(icopys);
+ icopys := icopys + GetDocDirCopies(CaseID,iDocDir);
+ ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
+ DocDirList.Delete(i);
+ end;
+ end;
+ if str = '' then
+ Str := Format('%s'+#9+'%d'+#9+'%s',[DocNo,iCopys,FromCaseID])
+ else
+ Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%s',[DocNo,iCopys,FromCaseID]);
+ end;
+ end;
+ DocDirList.Delete(0);
+ end;
+ finally
+ DocDirList.Free;
+ DocDir_CopiesList.Free;
+ FileList.Free;
+ end;
+ Result := Str;
+end;
+
+Function TCB_IMGPSScanX.CreateCustDocNoFrom_Info(CaseID:String):String; //產生被引進的自定文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+var
+ i,n : Integer;
+ DocDirList,FileList : TStringlist;
+ DocNo,DocName,iDocDir,iDocNo,iEdit:String;
+ FromCaseID : string;
+ icopys,ipages : integer;
+ S,S1 : TStringlist;
+ Str : String;
+begin
+ DocDirList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ Str := '';
+ if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
+ DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ while DocDirList.Count > 0 do
+ begin
+ iDocDir := DocDirList.Strings[0];
+ DocNo := DocNoDir2DocNo(iDocDir);
+ if Copy(iDocDir,1,5) = 'ZZZZZ' then //是自定文件
+ begin
+ //icopys := 1;
+ //icopys := GetDocNoCount(CaseID,DocNo);
+ icopys := GetDocDirCopies(CaseID,iDocDir);
+ ipages := GetDocDir_Page(CaseID,iDocDir);
+ iEdit := GetDocNoEdit(CaseID,DocNo,DocName);
+ FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
+ if FromCaseID <> '' then
+ begin
+ for i := DocDirList.Count - 1 downto 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocNo := DocNoDir2DocNo(iDocDir);
+ if (iDocNo = DocNo) and (GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir)<>'') then
+ begin
+ FromCaseID := GetUseCase('F',DisplayPath,iDocDir);
+ //inc(icopys);
+ ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
+ DocDirList.Delete(i);
+ end;
+ end;
+ DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
+ if str = '' then
+ Str := Format('%s'+#9+'%d'+#9+'%s',[DocName,iCopys,FromCaseID])
+ else
+ Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%s',[DocName,iCopys,FromCaseID]);
+ end;
+ end;
+ DocDirList.Delete(0);
+ end;
+ finally
+ DocDirList.Free;
+ FileList.Free;
+ end;
+ Result := Str;
+end;
+
+Function TCB_IMGPSScanX.GetDocNoEdit(CaseID,DocNo,DocName:String):String; //取出DocNo是否被異動 (Y/N)
+var
+ i : Integer;
+ EditedDocDirList : TStringlist;
+ C_DocNoList,C_DocNameList : TStringlist;
+begin
+ Result := 'N';
+ EditedDocDirList := TStringlist.Create;
+ C_DocNoList := TStringlist.Create;
+ C_DocNameList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
+ EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
+ C_DocNoList.StrictDelimiter := True;
+ C_DocNoList.Delimiter := #9;
+ C_DocNoList.DelimitedText := FC_DocNoList;
+ C_DocNameList.StrictDelimiter := True;
+ C_DocNameList.Delimiter := #9;
+ C_DocNameList.DelimitedText := FC_DocNameList;
+
+ //Showmessage(C_DocNoList.Text);
+ if (DocName = '') and (C_DocNoList.IndexOf(DocNo)=-1 ) then
+ Result := 'Y';
+ if (DocName <> '') and (C_DocNameList.IndexOf(DocName)=-1) then
+ Result := 'Y';
+ for i := 0 to EditedDocDirList.Count - 1 do
+ begin
+ if (DocNo = DocNoDir2DocNo(EditedDocDirList.Strings[i])) then
+ begin
+ Result := 'Y';
+ Break;
+ end;
+ end;
+ finally
+ EditedDocDirList.Free;
+ C_DocNoList.Free;
+ C_DocNameList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocNo_Count(Path,DocNo:String):Integer; //取出文件份數
+var
+ i : Integer;
+ iCopys : integer;
+ S,S1 : TStringlist;
+ iFormID : String;
+ DocFirst : Boolean;
+begin
+ Result := 0;
+ if not DocnoNeedGroup(DocNo) then
+ begin
+ Result := 1;
+ Exit;
+ end;
+
+ S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ S.LoadFromFile(Path+'Context.dat');
+ S1.LoadFromFile(Path+'Context_DocNo.dat');
+ iCopys := 0;
+
+ for i := 0 to S.Count - 1 do
+ begin
+ iFormID := FileName2FormCode(S.Strings[i]);
+ DocFirst := False;
+ if FormCode2Page(iFormID) = '01' then
+ DocFirst := True;
+ if ((iCopys = 0) or DocFirst) and (Docno = S1.Strings[i]) then
+ begin
+ inc(iCopys);
+ end;
+ end;
+ Result := iCopys;
+ finally
+ S.Free;
+ S1.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetDocNo_Page(Path,DocNo:String):Integer; //取出文件總頁數
+var
+ i : Integer;
+ ipages : integer;
+ S,S1 : TStringlist;
+begin
+ Result := 0;
+ S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ S.LoadFromFile(Path+'Context.dat');
+ S1.LoadFromFile(Path+'Context_DocNo.dat');
+ iPages := 0;
+ for i := 0 to S.Count - 1 do
+ begin
+ if Docno = S1.Strings[i] then
+ begin
+ inc(iPages);
+ end;
+ end;
+ Result := ipages;
+ finally
+ S.Free;
+ S1.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.Case_DocNoExists(CaseID,Docno:String):Boolean; //Docno是否存在案件裡
+var
+ i : Integer;
+ S : TStringlist;
+ iDocNo : String;
+begin
+ Result := False;
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(ImageSavePath + CaseID+'\Context.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+ iDocNo := FormCode2DocNo(FileName2FormCode(S.Strings[i]));
+ if Docno = iDocNo then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.ReSortFileName(Path:String); //檔名重新排序
+var
+ i : Integer;
+ OldName,NewName : String;
+ Filelist : TStringlist;
+begin
+ Filelist := TStringlist.Create;
+ try
+ if FileExists(Path+'Context.dat') then
+ begin
+ Filelist.LoadFromFile(Path+'Context.dat');
+ for i := 0 to Filelist.Count - 1 do
+ begin
+ OldName := Filelist.Strings[i];
+ //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
+//ShowMessage(OldName+#10#13+NewName);
+ ReNameFile(Path+OldName,Path+NewName);
+ Filelist.Strings[i] := NewName;
+ end;
+ Filelist.SaveToFile(Path+'Context.dat');
+ ContextList.LoadFromFile(Path+'Context.dat');
+ end;
+ finally
+ Filelist.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ReSortFileName_New(Path:String); //檔名重新排序
+var
+ i : Integer;
+ OldName,NewName : String;
+ Filelist : TStringlist;
+begin
+ Filelist := TStringlist.Create;
+ try
+ if FileExists(Path+'Context.dat') then
+ begin
+ Filelist.LoadFromFile(Path+'Context.dat');
+ for i := Filelist.Count - 1 downto 0 do
+ begin
+ OldName := Filelist.Strings[i];
+ //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
+ ReNameFile(Path+OldName,Path+NewName);
+ Filelist.Strings[i] := NewName;
+ end;
+ Filelist.SaveToFile(Path+'Context.dat');
+ ContextList.LoadFromFile(Path+'Context.dat');
+ end;
+ finally
+ Filelist.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CaseAsk(CaseID: string):Integer;
+var
+ SendData : String;
+begin
+//Memo1.Clear;
+ SendData := 'data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&case_no='+CaseID+'&work_no='+FWork_no;
+ if (FMode = 'NSCAN') or (FMode = 'DSCAN') then
+ begin
+//ShowMessage('JJJJJ');
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC05/isnew',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := -1;
+ Exit;
+ end;
+ end;
+//ShowMessage(SendData);
+
+ IF memo1.Lines.Strings[0] <> '0' Then
+ begin
+ HttpErrStr := _Msg('')+memo1.Lines.Strings[1]+'。';
+ Result := -1;
+ Exit;
+ end
+ Else
+ begin
+ if (memo1.Lines.Count < 2) then
+ begin
+ HttpErrStr := _Msg('')+'OCX:Index Count error';
+ Result := -1;
+ Exit;
+ end
+ Else
+ begin
+ if memo1.Lines.Strings[1] = '0' then
+ begin
+ Result := 0;
+ end
+ Else if memo1.Lines.Strings[1] = '1' then
+ Result := 1
+ Else
+ begin
+ HttpErrStr := _Msg('')+'OCX:Value error';
+ Result := -1;
+ Exit;
+ end;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CaseComplete(Path,CaseID:String;MainCase:Boolean):Boolean; //通知傳送完成
+var
+ OMRValue,Batchnum,Usermemo,Checkmemo,UpformID,ReMoveMemo: String;
+ Case_type,Handle_no,Format_id,Cen_Uid,Cen_Cliname,Cen_Platno,Cen_Apolyno,Case_priority : String;
+ Pages : Integer;
+ EnCodeDateTime : String;
+ SendData : String;
+ S : TStringlist;
+ i,v,v1 : Integer;
+ UpSortID : String;
+begin
+ Result := True;
+ S := TStringlist.Create;
+ try
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+
+ UpformID := GetCaseFormID(Path);
+
+
+ Case_type := '0';
+ if FileExists(Path+'Context.dat') then //掃描頁數
+ begin
+ S.LoadFromFile(Path+'Context.dat');
+ Pages := S.Count;
+ end;
+ if not FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then //如果沒這個檔就重產生預設值
+ begin
+ ClearCaseIndex;
+ WriteCaseIndex(ImageSavePath+CaseID+'\');
+ end;
+ {if FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\CaseIndex.dat');
+
+ Handle_No := S.Strings[0]; //經辦代號
+ Cen_Uid := S.Strings[1]; //被保人ID
+ Cen_Cliname := S.Strings[2]; //被保人姓名
+ Cen_Platno := S.Strings[3]; //車號
+ Case_Priority := S.Strings[4];//案件等級
+ if FMode = 'SSCAN' then //簽署章件的時候一律傳Format_ID
+ begin
+ Format_ID := S.Strings[5]; //主鍵值 (報價單號or續保單號or保單號碼or保險證號)
+ end
+ Else
+ begin
+ if (Length(UpformID) = 12) and (UpformID[2] = '-') then
+ Format_ID := S.Strings[5] //主鍵值 (報價單號or續保單號or保單號碼or保險證號)
+ else
+ Cen_Apolyno := S.Strings[5]; //強制證號
+ end;
+ if (FMode = 'MSCAN') and (length(Format_ID) = 16) and (Copy(Format_ID,1,2) = '05') then
+ begin
+ Format_ID := Copy(Format_ID,3,14); //20130606 yuu說監理站件的主鍵值為16碼且開開為05的要去掉
+ end;
+
+ end; }
+ if FileExists(ImageSavePath+CaseID+'\GetValue.xml') then //掃描帶值
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\GetValue.xml');
+ OMRValue := Trim(S.Text);
+ end;
+ if MainCase then //雙主約的主要案件
+ begin
+ if FileExists(ImageSavePath+CaseID+'\Batchnum.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\Batchnum.dat');
+ Batchnum := Trim(S.Text);
+ end;
+ end
+ Else //雙主約的第二案件
+ begin
+ if FileExists(ImageSavePath+CaseID+'\SecBatchnum.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\SecBatchnum.dat');
+ Batchnum := Trim(S.Text);
+ end;
+ end;
+ if FileExists(ImageSavePath+CaseID+'\Scan_Memo.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\Scan_Memo.dat');
+ Usermemo := Trim(S.Text);
+ end;
+ if FileExists(ImageSavePath+CaseID+'\CheckMemo.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\CheckMemo.dat');
+ Checkmemo := Trim(S.Text);
+ end;
+
+ if FileExists(ImageSavePath+CaseID+'\RemoveMemo.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\RemoveMemo.dat');
+ ReMoveMemo := Trim(S.Text);
+ end;
+
+
+ finally
+ S.Free;
+ end;
+ case_priority:='0';
+ if (FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') then
+ begin
+ SendData := 'checktime='+EnCodeDateTime
+ +'&work_no='+FWork_No //作業別
+ +'&case_id='+CaseID //受理編號
+ +'&form_id='+UpformID //表單代號
+ +'&scan_page='+inttostr(pages) //掃描頁數
+ +'&scan_get_value='+HTTPEncode(UTF8Encode(OMRValue)) //掃描帶值
+ +'&case_priority='+case_priority //案件等級
+ +'&batch_no='+batchnum //車隊批號
+ +'&user_memo='+HTTPEncode(UTF8Encode(usermemo)) //使用者註記
+ +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo)) //檢核註記
+ +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo)) //檢核移除註記
+ +'&case_type='+Case_type //進件種類 進件0 歸檔1
+ +'&handle_no='+Handle_no //經辦代號
+ +'&format_id='+Format_id //案件主鍵值
+ +'&cen_uid='+Cen_Uid //被保人ID
+ +'&cen_cliname='+HTTPEncode(UTF8Encode(Cen_Cliname)) //被保人姓名
+ +'&cen_platno='+Cen_Platno //車牌
+ +'&cen_apolyno='+Cen_Apolyno //強制證號
+ +'&has_authorize='+Has_Authorize; //是否有授權書影像
+ Showmessage(SendData);
+ if not RejectCase then
+ begin
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC05',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end
+ Else
+ begin
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC06',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end;
+
+
+ end
+ Else if FMode = 'ISCAN' then
+ begin
+ SendData := 'checktime='+EnCodeDateTime
+ +'&work_no='+FWork_No
+ +'&case_id='+CaseID
+ +'&form_id='+UpformID
+ +'&format_id='+Format_id
+ +'&scan_page='+inttostr(pages)
+ +'&user_memo='+HTTPEncode(UTF8Encode(usermemo))
+ +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo))
+ +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo))
+ +'&has_authorize='+Has_Authorize; //是否有授權書影像
+ //Showmessage(SendData);
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC08',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end
+ Else if FMode = 'FSCAN' then
+ begin
+ SendData := 'checktime='+EnCodeDateTime
+ +'&work_no='+FWork_No
+ +'&case_id='+CaseID
+ +'&scan_page='+inttostr(pages)
+ +'&user_memo='+HTTPEncode(UTF8Encode(usermemo))
+ +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo))
+ +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo))
+ +'&has_authorize='+Has_Authorize; //是否有授權書影像
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC09',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end
+ Else if FMode = 'RSCAN' then
+ begin
+ SendData := 'checktime='+EnCodeDateTime
+ +'&act=rescan'
+ +'&workno='+FWork_No
+ +'&caseid='+CaseID
+ +'&formid='+UpformID
+ +'&scanpage='+inttostr(pages)
+ // +'&areano='+FUserArea
+ +'&scangetvalue='+HTTPEncode(UTF8Encode(OMRValue))
+ +'&usermemo='+HTTPEncode(UTF8Encode(usermemo))
+ +'&checkmemo='+HTTPEncode(UTF8Encode(checkmemo))
+ +'&removememo='+HTTPEncode(UTF8Encode(ReMoveMemo))
+ +'&has_authorize='+Has_Authorize; //是否有授權書影像
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC01',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end
+ Else if FMode = 'ESCAN' then
+ begin
+ SendData := 'checktime='+EnCodeDateTime
+ +'&act=escan'
+ +'&workno='+FWork_No
+ +'&caseid='+CaseID
+ +'&formid='+UpformID
+ +'&scanpage='+inttostr(pages)
+ +'&batchnum='+batchnum
+ +'&usermemo='+HTTPEncode(UTF8Encode(usermemo))
+ +'&checkmemo='+HTTPEncode(UTF8Encode(checkmemo))
+ +'&removememo='+HTTPEncode(UTF8Encode(ReMoveMemo))
+ +'&has_authorize='+Has_Authorize; //是否有授權書影像
+ If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC01',SendData,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ end;
+
+ if Memo1.Lines.Strings[0] <> '0'then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+Memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.Set_caseid(const Value: WideString);
+begin
+ FCaseID := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_data(const Value: WideString);
+begin
+ FData := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_c_docnolist(const Value: WideString);
+begin
+ FC_DocNoList := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_fixfilelist(const Value: WideString);
+begin
+ FFixFileList := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_oldcaseinfo(const Value: WideString);
+begin
+ FOldCaseInfo := Value;
+end;
+
+function TCB_IMGPSScanX.Get_c_docnolist: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_caseid: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_data: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_fixfilelist: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_oldcaseinfo: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_is_oldcase: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_is_oldcase(const Value: WideString);
+begin
+ FIs_OldCase := UpperCase(Value);
+end;
+
+function TCB_IMGPSScanX.Get_casenolength: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_filesizelimit: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_casenolength(const Value: WideString);
+begin
+ if Value ='' then
+ begin
+ FCaseNoLength := 0 ;
+ CaseIDLength := FCaseNoLength;
+ end
+ else
+ begin
+ FCaseNoLength := StrToInt(Value) ;
+ CaseIDLength := FCaseNoLength;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.Set_filesizelimit(const Value: WideString);
+begin
+//ShowMessage(Value);
+ FFileSizeLimit:=0;
+ if Value ='' then
+ begin
+ FFileSizeLimit := 5*1024;
+ end
+ else
+ begin
+ FFileSizeLimit := StrToInt(Value);
+ end;
+
+end;
+
diff --git a/separate/scanImp/CB_IMGPSScanImp_Data.ts b/separate/scanImp/CB_IMGPSScanImp_Data.ts
new file mode 100644
index 0000000..6fbea50
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Data.ts
@@ -0,0 +1,819 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+export function applyDataMixins(cls: any) {
+
+ cls.prototype.Get_HelpFile = function(): string {
+ let Result = String(this.HelpFile);
+ return Result;
+ };
+
+ cls.prototype.Set_HelpFile = function(Value: string): void {
+ this.HelpFile = String(Value);
+ };
+
+ cls.prototype.DocNoIsExistImg = function(DocNopath: string): boolean {
+ let i: number;
+ let ST: any;
+ let Result = false;
+ ST = new this.TStringList();
+ if (fs.existsSync(DocNopath + '\\Context.dat')) { /////20190319 Hong 當有空的Docno目錄時會掛掉,增加這行
+ ST.LoadFromFile(DocNopath + '\\Context.dat');
+ }
+ for (i = 0; i < ST.Count; i++) {
+ if (this.ISExistImg(DocNopath + ST.Strings[i])) {
+ Result = false;
+ return Result; // Exit;
+ // Break;
+ }
+ }
+ Result = true;
+ return Result;
+ };
+
+ cls.prototype.HTTPSClientCertificateValidate = function(Sender: any, X509Certificate: any, Validate: { val: boolean }): void {
+ Validate.val = true;
+ };
+
+ cls.prototype.HTTPSClientRedirection = function(Sender: any, OldURL: string, NewURL: { val: string }, AllowRedirection: { val: boolean }): void {
+ AllowRedirection.val = true;
+ };
+
+ cls.prototype.GetServerDate = function(): boolean {
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/servertimeforocx', '', this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ this.ServerDate = this.Memo1.Lines.Strings[1];
+ this.ServerTime = this.ServerDate.substring(8, 14); // Copy(ServerDate,9,6)
+ this.ServerDate = this.ServerDate.substring(0, 8); // Copy(ServerDate,1,8)
+ this.Balance = this.GetBalance(this.ServerTime); //Server 跟Local的時間差
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf1 = function(): boolean { //取系統設定資訊Mode1 DOC_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+
+ ColumeStr = 'WORK_NO,DOC_NO,DOC_U_DESC,DOC_TYPE,DOC_VERSION,FORM_PAGES,START_DATE,STOP_DATE,IS_DOC_DIV,IS_IN_WH';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=1&col='+Doc_Inf_Colume+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=1&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.Doc_Inf_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf2 = function(): boolean { //取系統設定資訊Mode2 DM_FORM_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ ColumeStr = 'WORK_NO,MAIN_FORM_ID,DOC_VERSION,DEPE_FORM_ID,MUTEX_FORM_ID';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=2&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=2&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.DM_FORM_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf3 = function(): boolean { //取系統設定資訊mode3 FORM_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ //ColumeStr := 'T1.WORK_NO,T1.FORM_ID,T1.DOC_KIND,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.MERGE_IMAGE,T1.CC_FORM_ID,T1.CC_MERGE_FORMID,T2.DOC_TYPE'; {T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
+ ColumeStr = 'T1.WORK_NO,T1.FORM_ID,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.IS_PRINT,T2.DOC_TYPE'; //{T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=3&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=3&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.FORM_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf4 = function(): boolean { //取系統設定資訊mode4 CHECK_RULE_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ ColumeStr = 'WORK_NO,CHECK_NO,CHECK_RULE_DESC,MESG_SHOW_TYPE,MESG_DISP_TYPE,CHECK_MESG,SCAN_MODE';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=4&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=4&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.CHECK_RULE_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ this.CheckRule2OMRErrInfo();
+ return Result;
+ };
+
+ cls.prototype.GetSetInf5 = function(): boolean { //取系統設定資訊mode5 MEMO_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ ColumeStr = 'T1.WORK_NO,T1.MEMO_TYPE,T1.MEMO_CONTENT,T2.MEMO_TYPE_NAME';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=5&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.MEMO_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf6 = function(): boolean { //取系統設定資訊mode5 WORK_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ ColumeStr = 'WORK_NO,PARA_NO,PARA_CONTENT';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=6&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.WORK_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.GetSetInf7 = function(): boolean { //取系統設定資訊mode5 LASTEST_FORM_INF
+ let ColumeStr: string;
+ let S: any;
+ let EnCodeDateTime: string;
+ //SELECT FORM_ID,DOC_NO,DOC_VERSION FROM FORM_INF WHERE (DOC_NO,DOC_VERSION) in (SELECT DOC_NO, MAX(DOC_VERSION) FROM FORM_INF GROUP BY DOC_NO) ORDER BY DOC_NO
+
+ let Result = false; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ EnCodeDateTime = this.En_DecryptionStr_Base64('E', this.ServerDate + this.GetBalance2Time(this.Balance), this.Mpskey);
+ ColumeStr = 'FORM_ID,DOC_NO';
+ //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
+ if (!this.ProcessServlet_Get(this.HTTPSClient, this.FUrl + 'service/imgpsc/IMGPSC01/tables', 'checktime=' + EnCodeDateTime + '&mode=7&col=' + this.En_DecryptionStr_Base64('E', ColumeStr, this.Mpskey) + '&work_no=' + this.FWork_no, this.FReWrite, this.Memo1, false)) {
+ this.HttpErrStr = this._Msg('錯誤代碼:') + this.HttpError.HttpErrorCode.toString() + ',' + this.HttpError.HttpReason;
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this.Memo1.Lines.Strings[1];
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Strings[0] === '0') {
+ S = new this.TStringList();
+ S.Text = this.Memo1.Lines.Text;
+ this.SetSQLData(ColumeStr, S, this.LASTEST_FORM_INF_List);
+ S.Free();
+ Result = true;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/CW00/login.js"></script>') >= 0) {
+ this.HttpErrStr = this._Msg('錯誤原因:') + this._Msg('閒置過久或被登出,請重新登入');
+ Result = false;
+ return Result; // Exit;
+ }
+ return Result;
+ };
+
+ cls.prototype.SetIn_WH_DocNo = function(): void { //將要入庫的DocNo抽出來另存入list裡
+ let i: number;
+ for (i = 1; i < this.Doc_Inf_List.Count; i++) {
+ if (this.GetSQLData(this.Doc_Inf_List, 'IS_IN_WH', i) === 'Y') {
+ this.IN_WH_DocNoList.Add(this.GetSQLData(this.Doc_Inf_List, 'DOC_NO', i));
+ }
+ }
+ // {Showmessage(IN_WH_DocNoList.Text);
+ // StringtoFile(IN_WH_DocNoList.Text,'D:\121.txt');}
+ };
+
+ cls.prototype.DeleteDocNoFile = function(Path: string, DocNo: string): boolean { //刪除指定DocNo文件
+ let i: number;
+ let FName: string;
+ let Result = false;
+ for (i = this.ContextList.Count - 1; i >= 0; i--) {
+ FName = this.ContextList.Strings[i];
+ if (DocNo === this.FormCode2DocNo(this.FileName2FormCode(FName))) {
+ if (fs.existsSync(Path + FName)) fs.unlinkSync(Path + FName); // DeleteFile(Path+FName);
+ this.ContextList.Delete(i);
+ this.Context_DocnoList.Delete(i);
+ Result = true; //有刪到指定文件
+ }
+ }
+ this.ContextList.SaveToFile(Path + 'Context.dat');
+ this.Context_DocnoList.SaveToFile(Path + 'Context_DocNo.dat');
+ this.ReSortFileName(Path);
+ this.ContextList.LoadFromFile(Path + 'Context.dat');
+ this.Context_DocnoList.LoadFromFile(Path + 'Context_DocNo.dat');
+ if (fs.existsSync(Path + 'CustomDocNo.dat')) {
+ this.Cust_DocNoList.LoadFromFile(Path + 'CustomDocNo.dat');
+ }
+ return Result;
+ };
+
+ cls.prototype.DeleteShowFile = function(Path: string): void { //刪除顯示中的影像
+ let i: number;
+ let DelFile: string;
+ for (i = 0; i < this.NowShowFileList.Count; i++) {
+ DelFile = this.NowShowFileList.Strings[i];
+ if (fs.existsSync(Path + DelFile)) fs.unlinkSync(Path + DelFile); // DeleteFile(Path+DelFile);
+ this.SetContextList('D', -1, this.NowCaseno, this.NowDocNo, DelFile);
+ }
+ };
+
+ cls.prototype.GetDataDocNoPage = function(MainDocNo: string, MainVersion: string): number { //取記錄的文件_版本頁數
+ let P: string;
+ let Result = 0;
+ if (this.FindSQLData(this.Doc_Inf_List, 'FORM_PAGES', 'DOC_NO,DOC_VERSION', MainDocNo + ',' + MainVersion, 0, this.FindResult)) {
+ P = this.GetFindResult('FORM_PAGES');
+ if (P !== '') {
+ Result = parseInt(P, 10);
+ } else {
+ Result = 0;
+ }
+ }
+ return Result;
+ };
+
+ cls.prototype.CheckCaseDocNoPage = function(CaseID: string, DocNo: string, Version: string, Pages: number): number { //取案件裡的文件_版本頁數
+ let i: number, n: number, Count: number;
+ let S: any, S2: any;
+ let FormCode: string, iPage: string;
+ let docInt = 0, tempInt = 0;
+ let v: number, v2: number;
+
+ Count = 0;
+ docInt = 0;
+ tempInt = 0;
+ S = new this.TStringList();
+ S2 = new this.TStringList();
+ //ShowMessage('page='+IntToStr(Pages));
+ try {
+ S.LoadFromFile(this.ImageSavePath + CaseID + '\\upload\\Context.dat');
+ S2.LoadFromFile(this.ImageSavePath + CaseID + '\\upload\\DocDir.dat'); //2017 1220 改成只承認第一份的
+
+ for (i = 1; i <= Pages; i++) { //從0到pages-1 改成 1到pages 20170316 這樣可以修改檢核的頁數問題
+ iPage = this.Add_Zoo(i, 2);
+ for (n = 0; n < S.Count; n++) {
+ if (this.FWH_category === 'N' && this.FIs_In_Wh === 'Y') {
+ if (this.ISExistImg(this.ImageSavePath + CaseID + '\\upload\\' + S.Strings[n])) {
+ continue;
+ }
+ }
+
+ if (S2.Strings[n].length > 8 && S2.Strings[n].indexOf(DocNo) !== -1) { //2017 1220 改成只承認第一份的
+ //LogFile1.LogToFile(logTimeString+'有進'+docno+','+S2.Strings[n]+IntToStr(Pos(DocNo,S2.Strings[n])));
+ v = S2.Strings[n].indexOf('(');
+ v2 = S2.Strings[n].indexOf(')');
+ tempInt = parseInt(S2.Strings[n].substring(v + 1, v2), 10);
+
+ if (docInt === 0) {
+ docInt = tempInt;
+ }
+ if (docInt !== tempInt) {
+ //LogFile1.LogToFile(logTimeString+'docInt='+IntToStr(docInt)+',tempInt='+IntToStr(tempInt));
+ return Count; // Break returning Count
+ }
+ }
+
+ FormCode = this.FileName2FormCode(S.Strings[n]);
+ //LogFile1.LogToFile(logTimeString+'S.Strings[n]='+S.Strings[n]);
+ //Showmessage('1:'+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
+ //LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
+ this.LogFile1.LogToFile(this.logTimeString() + 'CheckCaseDocNoPage caseno=' + CaseID + ',' + Version + ',' + this.FormCode2Version(FormCode) + ',' + DocNo + ',' + this.FormCode2DocNo(FormCode) + ',' + iPage + ',' + this.FormCode2Page(FormCode));
+ //ShowMessage(DocNo+','+IntToStr(docInt)+','+IntToStr(tempInt));
+ //LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
+ if (Version === this.FormCode2Version(FormCode) && DocNo === this.FormCode2DocNo(FormCode) && iPage === this.FormCode2Page(FormCode)) {
+ this.LogFile1.LogToFile(this.logTimeString() + 'CheckCaseDocNoPage caseno=' + CaseID + ',' + Version + ',' + this.FormCode2Version(FormCode) + ',' + DocNo + ',' + this.FormCode2DocNo(FormCode) + ',' + iPage + ',' + this.FormCode2Page(FormCode));
+ //Showmessage(version+','+DocNo+',iPage='+iPage);
+ //Showmessage(inttostr(Count+1));
+ Count++;
+ break; //找到了...離開
+ }
+ }
+ }
+ } finally {
+ S.Free();
+ S2.Free();
+ }
+ return Count;
+ };
+
+ cls.prototype.TransCaseID = function(Path: string, CaseID: string, MainCase: boolean): boolean { //傳送案件
+ let i: number, n: number, v: number;
+ let ZipFileList: any;
+ let UpFormID: string;
+ let pages: number;
+ let TransName: string;
+ let MaskPath: string;
+ let HaveMask = false;
+ let S: string;
+ let SendData: string;
+ let Doc_Data = '', Doc_Data1 = '';
+ let In_Doc1 = '', In_Doc2 = '';
+ let AttachYN: string; //是否有附件 Y:有 N:沒有
+
+ let ST1: any, ST2: any, ST3: any;
+ let str1 = '', str2 = '';
+ let must_formidStr = '';
+ let last_add_formidstr = '';
+ let ScanListStr = '';
+ let casepath: string;
+ let filesizeInt = 0;
+ let case_page: string;
+ let Fname: string;
+ let FileRec: any;
+
+ let Result = true;
+ TransName = CaseID;
+ MaskPath = Path + 'MaskImg\\';
+ if (fs.existsSync(Path + 'Context.dat')) {
+ this.ContextList.LoadFromFile(Path + 'Context.dat');
+ this.Context_DocnoList.LoadFromFile(Path + 'Context_DocNo.dat');
+ }
+
+ if (fs.existsSync(Path + 'CustomDocNo.dat')) {
+ this.Cust_DocNoList.LoadFromFile(Path + 'CustomDocNo.dat');
+ }
+
+ pages = this.ContextList.Count;
+ case_page = pages.toString();
+ if (this.FMode === 'NSCAN' || this.FMode === 'ESCAN' || this.FMode === 'ASCAN' || this.FMode === 'DSCAN' || this.FMode === 'SSCAN' || this.FMode === 'MSCAN' || this.FMode === 'RI_SCAN' || this.FMode === 'RSCAN') {
+ //Showmessage('1');
+ UpFormID = this.GetCaseFormID(Path);
+ //{if UpformID = '' then //20131213 yuu說不管主form
+ //begin
+ // Showmessage(_msg('取不到主FormID!!'));
+ // Result := False;
+ // DataLoading(False,False);
+ // Exit;
+ //end;}
+ }
+
+ this.CaseResort2Scanlist(Path); //檔名照設定排序產生scanlist.dat
+ //CaseResort(Path); //檔名照設定排序
+ this.CreateFormID_FormName(Path, CaseID); //產生FormID_FormName.dat
+ this.CreateDocNo_DocName(Path, CaseID); //產生DocNo_Name.dat
+ Doc_Data = this.CreateDocNo_Info(CaseID); //產生保管袋文件 Docno,份數,頁數;Docno,份數,頁數 的回傳字串
+ Doc_Data1 = this.CreateCustDocNo_Info(CaseID); //產生自定文件 Docname,份數,頁數;Docno,份數,頁數 的回傳字串
+ In_Doc1 = this.CreateDocnoFrom_Info(CaseID); //產生被引進的保管袋文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+ In_Doc2 = this.CreateCustDocNoFrom_Info(CaseID); //產生被引進的自定文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+ AttachYN = this.CreateAttach_Info(CaseID); //是否還有附件 Y:有 N:沒有
+ this.ReadCaseIndex(Path);
+ //LoanDoc := 'Y';
+ //產生遮罩影像
+ // if FWork_No = 'CW' then
+ // HaveMask := Case2Mask(Path,MaskPath);
+ //產生遮罩影像
+ // S := S +#13+'5-->'+ Timetostr(now);
+
+ ///////必要formid 20170315 start //////////////////////////////
+ must_formidStr = '';
+ last_add_formidstr = '';
+ ST1 = new this.TStringList();
+ ST1.LoadFromFile(Path + 'FormCode_Name.dat');
+ //ShowMessage(ST1.Text);
+ //ShowMessage(LastInitFormidList.Text);
+ ST2 = new this.TStringList();
+ ST3 = new this.TStringList();
+
+ for (i = 0; i < ST1.Count; i++) {
+ if (ST1.Strings[i].indexOf('_') !== 0 && ST1.Strings[i].indexOf('_') !== -1) {
+ str1 = ST1.Strings[i].substring(0, ST1.Strings[i].indexOf('_'));
+ ST2.Add(str1);
+ must_formidStr = must_formidStr + str1 + '@#,';
+ }
+ }
+ must_formidStr = must_formidStr.substring(0, must_formidStr.length - 3);
+ //ShowMessage('must_formidStr='+must_formidStr);
+ //ShowMessage('AST2='+ST2.Text);
+
+
+ for (i = 0; i < this.LastInitFormidList.Count; i++) {
+ if (ST2.IndexOf(this.LastInitFormidList.Strings[i]) !== -1) {
+ ST2.Delete(ST2.IndexOf(this.LastInitFormidList.Strings[i]));
+ }
+ }
+ //ShowMessage('BST2='+ST2.Text);
+ for (i = 0; i < ST2.Count; i++) {
+ last_add_formidstr = last_add_formidstr + ST2.Strings[i] + '@#,';
+ }
+ last_add_formidstr = last_add_formidstr.substring(0, last_add_formidstr.length - 3);
+
+ ST3.LoadFromFile(Path + 'scanlist.dat');
+ for (i = 0; i < ST3.Count; i++) {
+ if (ScanListStr === '') {
+ ScanListStr = this.FileName2FormCode(ST3.Strings[i]);
+ } else {
+ ScanListStr = `${ScanListStr},${this.FileName2FormCode(ST3.Strings[i])}`;
+ }
+ }
+
+ ST1.Free();
+ ST2.Free();
+ ST3.Free();
+ //ShowMessage('last_add_formidstr='+last_add_formidstr);
+ ///////必要formid 20170315 end //////////////////////////
+
+ ///保留外部影像 start///////////////////////////////
+ casepath = Path.substring(0, Path.indexOf('Upload'));
+ //ShowMessage('casepath='+casepath);
+ //FIsExternal:='Y';
+ if (this.FMode === 'ESCAN' && this.FIsExternal === 'Y') {
+ if (fs.existsSync(casepath + 'Download\\FirstImg.zip')) {
+ fs.copyFileSync(casepath + 'Download\\FirstImg.zip', Path + 'FirstImg.zip');
+ }
+ else {
+ fs.copyFileSync(casepath + 'Download\\' + CaseID + '.zip', Path + 'FirstImg.zip');
+ }
+ }
+ ///保留外部影像 end///////////////////////////////
+
+ //file_size 計算 就先不做 20170316
+ filesizeInt = 0;
+
+
+ //////壓檔/////
+ this.ZipMainFile(Path, Path, 'Img.zip');
+ if (HaveMask) {
+ this.ZipMaskFile(Path, MaskPath, Path, 'MaskImg.zip'); //有遮罩設定的才產生
+ }
+ /////壓檔////
+ ///檢查上傳的zip大小////
+ Fname = Path + 'Img.zip';
+
+ // FindFirst(FName, faAnyfile, FileRec);
+ // NodeJS equivalent using fs.statSync
+ let stat = fs.statSync(Fname);
+
+ //FMaxUploadSize
+ //ShowMessage(IntToStr(FileRec.Size));
+ //Result:=False;
+ //exit; //目前上傳檔案大小為xxMB,已超過50MB,無法上傳 %.3f ,[FileRec.Size / 1048576]
+ if (stat.size > parseInt(this.FMaxUploadSize, 10) * 1048576) { // 檢查檔案大小
+ this.Showmessage(this.Format(this._Msg('%s目前上傳檔案大小為%.3fMB,已超過%sMB,無法上傳'), [CaseID, stat.size / 1048576, this.FMaxUploadSize]));
+ //ShowMessage(Format('%s目前上傳檔案大小為%.3fMB,已超過'+FMaxUploadSize+'MB,無法上傳',[caseid,FileRec.Size / 1048576]) );
+ Result = false;
+ return Result; // Exit;
+ }
+ ///檢查上傳的zip大小////
+ //ShowMessage('last_add_formidstr='+last_add_formidstr);
+ if (!this.GetFtpinfo(CaseID, 'upload')) { //取案件上傳方式
+ //Showmessage(_Msg()Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+'.');
+ this.DownFileErrStr = this._Msg('取案件上傳資訊失敗!!') + this.HttpErrStr;
+ Result = false;
+ return Result; // Exit;
+ }
+ SendData = 'data=' + this.HTTPEncode(this.UTF8Encode(this.FData))
+ + '&verify=' + this.FVerify
+ + '&form_id=' + UpFormID
+ + '&loan_doc=' + this.Case_loandoc
+ + '&case_no=' + TransName
+ + '&doc_data=' + this.HTTPEncode(this.UTF8Encode(Doc_Data))
+ + '&doc_data1=' + this.HTTPEncode(this.UTF8Encode(Doc_Data1))
+ + '&attach=' + AttachYN
+ + '&case_page=' + case_page
+ + '&file_size=' + filesizeInt.toString()
+ + '&must_formid=' + must_formidStr //擁有的 formid
+ + '&last_add_formid=' + last_add_formidstr //當次新加的 formid
+ + '&form_code=' + ScanListStr //scanlist.dat 表單代號
+ + '&ftp_image_path=' + this.FFtpExtraPath //加傳FTP目錄 HTTP上傳時會是空白
+ + '&in_doc1=' + this.HTTPEncode(this.UTF8Encode(In_Doc1))
+ + '&in_doc2=' + this.HTTPEncode(this.UTF8Encode(In_Doc2));
+
+ if (this.TransMode === this.TTransMode.tsHttp) {
+ ////上傳/////
+ this.ShowText = CaseID + this._Msg('資料上傳中(Http),請稍候');
+ this.DataLoading(true, true);
+ if (!this.upFile(this.HTTPSClient, this.FUrl, 'service/imgpsc/IMGPSC02/caseupload', SendData, 'file', Path + 'Img.zip', this.FReWrite, this.Memo1, false)) {
+ this.Showmessage(this.HttpError.HttpErrorCode.toString() + ' ' + this.HttpError.HttpReason + '.');
+ Result = false;
+ return Result; // Exit;
+ }
+ if (this.Memo1.Lines.Strings[0] === '1') {
+ this.Showmessage(this.Format(this._Msg('') + this._Msg(''), [CaseID]) + this.Memo1.Lines.Strings[1] + '。');
+ Result = false;
+ return Result; // Exit;
+ }
+ else if (this.Memo1.Lines.Text.indexOf('<script type="text/javascript" src="scripts/IMGPS00/login.js"></script>') > 0) {
+ this.Showmessage(this.Format(this._Msg('') + this._Msg('') + this._Msg('閒置過久或被登出,請重新登入'), [CaseID]));
+ Result = false;
+ return Result; // Exit;
+ }
+ ////上傳////
+ } else if (this.TransMode === this.TTransMode.tsFtp) {
+ this.ShowText = CaseID + this._Msg('資料上傳中(Ftp),請稍候');
+ this.DataLoading(true, true);
+ this.SetFtpInfo();
+ try {
+ if (!this.IIS_Ftp.FtpsConnect()) {
+ this.Showmessage(this.Format('無法連上Ftp主機,錯誤原因:%s', [this.FtpErrReason]));
+ Result = false;
+ return Result; // Exit;
+ }
+ if (!this.IIS_Ftp.FtpsToMain(this.FFtpExtraPath, CaseID + '.zip', Path + 'Img.zip', this.display1)) {
+ this.Showmessage(this.Format(this._Msg('上傳案件(%s)時,發生錯誤,錯誤原因:%s'), [CaseID, this.FtpErrStr]));
+ Result = false;
+ return Result; // Exit;
+ }
+
+ if (!this.FtpCaseComplete(SendData)) { //Ftp上傳後通知完成
+ this.Showmessage(this.Format(this._Msg('通知案件(%s)Ftp上傳完成時,發生錯誤!!'), [CaseID]) + this.HttpErrStr);
+ Result = false;
+ return Result; // Exit;
+ }
+ } finally {
+ this.IIS_Ftp.FtpsClose();
+ }
+ }
+
+ if (this.FMode === 'ESCAN') { //上傳舊件引入檔案 //20140616 原本先搬舊件再搬新件,改為先搬新件再搬舊件
+ if (!this.TransOldCaseFile(this.ImageSavePath + CaseID + '\\')) {
+ Result = false;
+ return Result; // Exit;
+ }
+ }
+ // 呼叫Server完成 /////
+ //{If not CaseComplete(Path,CaseID,MainCase) Then
+ //begin
+ // Showmessage(_Msg('通知案件傳送完成時,網路發生錯誤!!')+HttpErrStr);
+ // DataLoading(False,False);
+ // Result := False;
+ // Exit;
+ //end; }
+ /// 呼叫Server完成////
+
+ ////刪檔////
+ //_DelTree(Path); //會只刪TransPath
+ //ShowMessage('STOP');
+ this._DelTree(this.ImageSavePath + CaseID);
+ this.SetCaseList('D', -1, CaseID);
+ ////刪檔////
+ return Result;
+ };
+
+ ['Set_caseid', 'Set_data', 'Set_c_docnolist', 'Set_fixfilelist', 'Set_oldcaseinfo'].forEach(p => {
+ cls.prototype[p] = function(v: string) {
+ let fieldName = 'F' + p.substring(4).replace('caseid', 'CaseID').replace('data', 'Data').replace('c_docnolist', 'C_DocNoList').replace('fixfilelist', 'FixFileList').replace('oldcaseinfo', 'OldCaseInfo');
+ this[fieldName] = v;
+ };
+ cls.prototype['Get_' + p.substring(4)] = function() {
+ let fieldName = 'F' + p.substring(4).replace('caseid', 'CaseID').replace('data', 'Data').replace('c_docnolist', 'C_DocNoList').replace('fixfilelist', 'FixFileList').replace('oldcaseinfo', 'OldCaseInfo');
+ return this[fieldName];
+ };
+ });
+
+ cls.prototype.Set_is_oldcase = function(v: string) { this.FIs_OldCase = v.toUpperCase(); };
+ cls.prototype.Get_is_oldcase = function() { return this.FIs_OldCase; };
+
+ cls.prototype.Set_casenolength = function(v: string) { this.FCaseNoLength = v === '' ? 0 : parseInt(v, 10); this.CaseIDLength = this.FCaseNoLength; };
+ cls.prototype.Get_casenolength = function() { return this.FCaseNoLength.toString(); };
+
+ cls.prototype.Set_filesizelimit = function(v: string) { this.FFileSizeLimit = v === '' ? 5120 : parseInt(v, 10); };
+ cls.prototype.Get_filesizelimit = function() { return this.FFileSizeLimit.toString(); };
+
+ cls.prototype.Set_check_main_form = function(v: string) { this.FCheck_main_form = v; };
+ cls.prototype.Get_check_main_form = function() { return this.FCheck_main_form; };
+
+ cls.prototype.Set_WH_CATEGORY = function(v: string) { this.FWH_category = v; };
+ cls.prototype.Get_WH_CATEGORY = function() { return this.FWH_category; };
+
+ cls.prototype.Set_isExternal = function(v: string) { this.FIsExternal = v; };
+ cls.prototype.Get_isExternal = function() { return this.FIsExternal; };
+
+ cls.prototype.Set_imgdelete = function(v: string) { this.FImgDelete = v; };
+ cls.prototype.Get_imgdelete = function() { return this.FImgDelete; };
+
+ cls.prototype.Set_custdocyn = function(v: string) { this.FCustDocYN = v.toUpperCase(); };
+ cls.prototype.Get_custdocyn = function() { return this.FCustDocYN; };
+
+ cls.prototype.Set_printyn = function(v: string) { this.FPrintyn = v.toUpperCase(); };
+ cls.prototype.Get_printyn = function() { return this.FPrintyn; };
+
+ cls.prototype.Set_work_no = function(v: string) { this.FWork_no = v; };
+ cls.prototype.Get_work_no = function() { return this.FWork_no; };
+
+ cls.prototype.Set_verify = function(v: string) { this.FVerify = v; };
+ cls.prototype.Get_verify = function() { return this.FVerify; };
+
+ cls.prototype.Set_userunit = function(v: string) { this.FUserUnit = v; };
+ cls.prototype.Get_userunit = function() { return this.FUserUnit; };
+
+ cls.prototype.Set_username = function(v: string) { this.FUserName = v; };
+ cls.prototype.Get_username = function() { return this.FUserName; };
+
+ cls.prototype.Set_userid = function(v: string) { this.FUserID = v; };
+ cls.prototype.Get_userid = function() { return this.FUserID; };
+
+ cls.prototype.Set_useproxy = function(v: string) { this.FUseProxy = v.toUpperCase(); };
+ cls.prototype.Get_useproxy = function() { return this.FUseProxy; };
+
+ cls.prototype.Set_url = function(v: string) { this.FUrl = v; };
+ cls.prototype.Get_url = function() { return this.FUrl; };
+
+ cls.prototype.Set_rewrite = function(v: string) { this.FReWrite = v; };
+ cls.prototype.Get_rewrite = function() { return this.FReWrite; };
+
+ cls.prototype.Set_modename = function(v: string) { this.FModeName = v; };
+ cls.prototype.Get_modename = function() { return this.FModeName; };
+
+ cls.prototype.Set_mode = function(v: string) { this.FMode = v.toUpperCase(); };
+ cls.prototype.Get_mode = function() { return this.FMode; };
+
+ cls.prototype.Set_loandoc_value = function(v: string) { this.FLoanDoc_Value = v; };
+ cls.prototype.Get_loandoc_value = function() { return this.FLoanDoc_Value; };
+
+ cls.prototype.Set_loandoc_enable = function(v: string) { this.FLoanDoc_Enable = v; };
+ cls.prototype.Get_loandoc_enable = function() { return this.FLoanDoc_Enable; };
+
+ cls.prototype.Set_language = function(v: string) {
+ this.FLanguage = v.toLowerCase();
+ if (this.FLanguage === 'zh-tw') {
+ this.FLanguage = 'zh_tw';
+ }
+ };
+ cls.prototype.Get_language = function() { return this.FLanguage; };
+
+ cls.prototype.Set_is_in_wh = function(v: string) { this.FIs_In_Wh = v.toUpperCase(); };
+ cls.prototype.Get_is_in_wh = function() { return this.FIs_In_Wh; };
+
+ cls.prototype.Set_c_docnamelist = function(v: string) { this.FC_DocNameList = v; };
+ cls.prototype.Get_c_docnamelist = function() { return this.FC_DocNameList; };
+
+ cls.prototype.DataLoading = function(Loading: boolean, UseTimer: boolean): void {
+ if (Loading) {
+ // Screen.Cursor := -11;
+ if (UseTimer) {
+ this.Panel22.Caption = this.ShowText;
+ this.Panel22.Left = Math.floor(this.Panel9.Width / 2) - Math.floor(this.Panel22.Width / 2);
+ this.Panel22.Top = Math.floor(this.Panel9.Height / 2) - Math.floor(this.Panel22.Height / 2);
+ this.Panel22.Visible = true;
+ this.Timer2.Enabled = true;
+ } else {
+ this.Panel8.Left = Math.floor(this.Panel9.Width / 2) - Math.floor(this.Panel8.Width / 2);
+ this.Panel8.Top = Math.floor(this.Panel9.Height / 2) - Math.floor(this.Panel8.Height / 2);
+ this.Panel8.Visible = true;
+ }
+ this.Application.ProcessMessages();
+ this.Panel1.Enabled = false;
+ this.Panel2.Enabled = false;
+ } else {
+ this.Panel22.Visible = false;
+ this.Panel8.Visible = false;
+ this.Timer2.Enabled = false;
+ this.Panel1.Enabled = true;
+ this.Panel2.Enabled = true;
+ // Screen.Cursor := 0;
+ }
+ };
+
+ cls.prototype.ReduceLogFile = function(): void {
+ let ST1: any;
+ let I: number;
+ ST1 = new this.TStringList();
+ if (fs.existsSync(this.LngPath + 'IMGPSCheck.log')) {
+ ST1.LoadFromFile(this.LngPath + 'IMGPSCheck.log');
+ if (ST1.Count > 100000) {
+ for (I = 0; I <= 10000; I++) {
+ ST1.Delete(0);
+ }
+ ST1.SaveToFile(this.LngPath + 'IMGPSCheck.log');
+ }
+ }
+ ST1.Free();
+ };
+
+ cls.prototype.ClearCaseIndex = function(): void {
+ this.AddCredit1RG.Enabled = false;
+ this.AddCredit1RG.ItemIndex = -1;
+ };
+
+}
diff --git a/separate/scanImp/CB_IMGPSScanImp_Main.pas b/separate/scanImp/CB_IMGPSScanImp_Main.pas
new file mode 100644
index 0000000..febdbe3
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Main.pas
@@ -0,0 +1,1089 @@
+unit CB_IMGPSScanImp;
+//TEST
+{$WARN SYMBOL_PLATFORM OFF}
+
+interface
+
+uses
+ EnScan, { for Scanner }
+ EnDiGrph, { for TDibGraphic }
+ EnMisc, { for MinFloat }
+ EnTifGr, { for TTifGraphic }
+ {$IFDEF Production}
+ CB_IMGPSScan_TLB,
+ {$ENDIF}
+ {$IFDEF Test}
+ CB_IMGPSScan_test_TLB,
+ {$ENDIF}
+
+ Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+ ActiveX, AxCtrls, StdVcl, VCLUnZip, VCLZip, Encryp,
+ ExtCtrls, ComCtrls, Menus, StdCtrls, Gauges, EnImgScr, PJMenuSpeedButtons,
+ Buttons, ImgList, SBSimpleSSL, SBHTTPSClient, SBWinCertStorage, SBX509,
+ SBCustomCertStorage, SBUtils,mpsBarco,BarcodesFinder,HTTPApp,ErrList,
+ Xmltool,inifiles,printers,IdHashMessageDigest, idHash, LogFile,ShellApi,
+ SBSocket,IIS_Ftp, SBSimpleFTPS;
+Type
+ TTransMode =(tsHttp,tsFtp,tsNone);
+
+var
+ Ch_WriteNote : Boolean;
+ RejectCase : Boolean;
+ ErrIndex : Integer;
+
+ //*****預設區*****//
+ Def_DeviceDelete : Boolean; //空白頁刪除啟動
+ Def_DeviceDeleteSize : Integer; //空白頁Size
+ Def_ScannerReverse : Boolean; //是否需反相
+ Def_BoardClear : Boolean; //是否清黑邊
+ Def_ScanDpi : Integer; //掃瞄DPI
+ Def_ScanDuplex : Boolean; //是否雙面掃瞄
+ Def_ScanRotate : Integer; //掃瞄時旋轉角度
+ Def_ScanDeskew : Boolean; //是否傾斜矯正
+ Def_ScanBright : Integer; //亮度
+ Def_ScanContrast : Integer; //對比
+ Def_ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
+ Def_ScanImgSetUse : Boolean; //是否使用亮度對比設定
+ //*****預設區*****//
+
+Const
+ ISBName = 'PreViewISB';
+
+{獲取自身版本號所需要 }
+type
+ TVersionLanguage = (vlArabic, vlBulgarian, vlCatalan, vlTraditionalChinese,
+ vlCzech, vlDanish, vlGerman, vlGreek, vlUSEnglish, vlCastilianSpanish,
+ vlFinnish, vlFrench, vlHebrew, vlHungarian, vlIcelandic, vlItalian,
+ vlJapanese, vlKorean, vlDutch, vlNorwegianBokmel, vlPolish,
+ vlBrazilianPortuguese, vlRhaetoRomanic, vlRomanian, vlRussian,
+ vlCroatoSerbian, vlSlovak, vlAlbanian, vlSwedish, vlThai, vlTurkish,
+ vlUrdu, vlBahasa, vlSimplifiedChinese, vlSwissGerman, vlUKEnglish,
+ vlMexicanSpanish, vlBelgianFrench, vlSwissItalian, vlBelgianDutch,
+ vlNorwegianNynorsk, vlPortuguese, vlSerboCroatian, vlCanadianFrench,
+ vlSwissFrench, vlUnknown);
+
+const LanguageValues: array[TVersionLanguage] of Word = ($0401, $0402, $0403,
+ $0404, $0405, $0406, $0407, $0408, $0409, $040A, $040B, $040C, $040D,
+ $040E, $040F, $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417,
+ $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F, $0420, $0421,
+ $0804, $0807, $0809, $080A, $080C, $0810, $0813, $0814, $0816, $081A,
+ $0C0C, $100C, $0000);
+{獲取自身版本號所需要 end}
+
+
+type
+ TScanMode = (smNew, smReplace, smInsert, smSample, smRTS);
+ TpScanInfo = ^TScanInfo;
+ TScanInfo = record
+ MultiPage : Boolean;
+ { supplementary info when MultiPage is True }
+ Graphic : TTiffGraphic;
+ Stream : TFileStream;
+ ImageCount : LongInt;
+ end;
+ TOMRErrInfo = record
+ Display : Boolean; //是否顯示
+ Ignore : Boolean; //可否刪除
+ Info : String;
+ Mode : String;
+ end;
+ TScrollRec = Record
+ HScroll : Integer;
+ VScroll : Integer;
+ Rate : Single;
+ end;
+
+type
+ TCB_IMGPSScanX = class(TActiveForm, ICB_IMGPSScanX)
+ Panel1: TPanel;
+ TransBtn: TBitBtn;
+ Panel21: TPanel;
+ ViewModeBtn: TPJMenuSpeedButton;
+ Button2: TButton;
+ Button1: TButton;
+ OptionBtn: TBitBtn;
+ SelectScanBtn: TBitBtn;
+ NextPageBtn: TBitBtn;
+ PrePageBtn: TBitBtn;
+ FC6: TBitBtn;
+ FC5: TBitBtn;
+ FC4: TBitBtn;
+ FC3: TBitBtn;
+ FC2: TBitBtn;
+ FC1: TBitBtn;
+ FC0: TBitBtn;
+ Panel23: TPanel;
+ PJLinkedMenuSpeedButton2: TPJLinkedMenuSpeedButton;
+ NewScanBtn: TBitBtn;
+ AddScanBtn: TBitBtn;
+ Panel4: TPanel;
+ Panel2: TPanel;
+ Splitter1: TSplitter;
+ Panel3: TPanel;
+ Label7: TLabel;
+ Panel6: TPanel;
+ CB1: TCheckBox;
+ ScanDuplexCB: TCheckBox;
+ ScanFlatCB: TCheckBox;
+ Panel18: TPanel;
+ Panel12: TPanel;
+ Panel7: TPanel;
+ Panel9: TPanel;
+ Shape1: TShape;
+ ImageScrollBox1: TImageScrollBox;
+ imgp8: TPanel;
+ lb8: TLabel;
+ ISB8: TImageScrollBox;
+ imgp7: TPanel;
+ lb7: TLabel;
+ ISB7: TImageScrollBox;
+ imgp6: TPanel;
+ lb6: TLabel;
+ ISB6: TImageScrollBox;
+ imgp5: TPanel;
+ lb5: TLabel;
+ ISB5: TImageScrollBox;
+ imgp4: TPanel;
+ lb4: TLabel;
+ ISB4: TImageScrollBox;
+ imgp3: TPanel;
+ lb3: TLabel;
+ ISB3: TImageScrollBox;
+ imgp2: TPanel;
+ lb2: TLabel;
+ ISB2: TImageScrollBox;
+ imgp1: TPanel;
+ lb1: TLabel;
+ Memo1: TMemo;
+ Display1: TMemo;
+ Panel22: TPanel;
+ Panel8: TPanel;
+ Label2: TLabel;
+ Gauge1: TGauge;
+ ScrollBar1: TScrollBar;
+ Panel10: TPanel;
+ PageLV: TListView;
+ StatusBar1: TStatusBar;
+ ImageList4: TImageList;
+ ImageList3: TImageList;
+ ImageList1: TImageList;
+ PopupMenu2: TPopupMenu;
+ mode1: TMenuItem;
+ mode2: TMenuItem;
+ mode3: TMenuItem;
+ mode4: TMenuItem;
+ N51: TMenuItem;
+ ImageList2: TImageList;
+ OpenDialog1: TOpenDialog;
+ PopupMenu3: TPopupMenu;
+ PM301: TMenuItem;
+ PM302: TMenuItem;
+ PM303: TMenuItem;
+ Timer1: TTimer;
+ TomEncryption1: TTomEncryption;
+ SaveDialog1: TSaveDialog;
+ Timer2: TTimer;
+ VCLZip1: TVCLZip;
+ PopupMenu4: TPopupMenu;
+ PM401: TMenuItem;
+ PM402: TMenuItem;
+ PM403: TMenuItem;
+ PM404: TMenuItem;
+ ElWinCertStorage: TElWinCertStorage;
+ ElMemoryCertStorage: TElMemoryCertStorage;
+ Panel5: TPanel;
+ AddCredit1RG: TRadioGroup;
+ Panel11: TPanel;
+ SampleScanBtn: TBitBtn;
+ WNoteBtn: TBitBtn;
+ PopupMenu1: TPopupMenu;
+ PM101: TMenuItem;
+ N12: TMenuItem;
+ PM102: TMenuItem;
+ MenuItem1: TMenuItem;
+ PM103: TMenuItem;
+ PM104: TMenuItem;
+ N7: TMenuItem;
+ PM106: TMenuItem;
+ PM107: TMenuItem;
+ PM108: TMenuItem;
+ PM109: TMenuItem;
+ PopupMenu5: TPopupMenu;
+ PM501: TMenuItem;
+ PM502: TMenuItem;
+ PM503: TMenuItem;
+ PM504: TMenuItem;
+ N5: TMenuItem;
+ PM505: TMenuItem;
+ PM506: TMenuItem;
+ N29: TMenuItem;
+ PM510: TMenuItem;
+ PM509: TMenuItem;
+ PM507: TMenuItem;
+ N15: TMenuItem;
+ PM508: TMenuItem;
+ ExportBt: TButton;
+ ImportBt: TButton;
+ CheckCaseBtn: TBitBtn;
+ DenialTimeLb: TLabel;
+ Panel14: TPanel;
+ ScrollBox1: TScrollBox;
+ Label1: TLabel;
+ Button3: TButton;
+ Panel15: TPanel;
+ Button4: TButton;
+ PopupMenu6: TPopupMenu;
+ PM602: TMenuItem;
+ PM601: TMenuItem;
+ PM605: TMenuItem;
+ PM603: TMenuItem;
+ PM604: TMenuItem;
+ N8: TMenuItem;
+ Panel16: TPanel;
+ SpeedButton3: TSpeedButton;
+ SpeedButton14: TSpeedButton;
+ SpeedButton15: TSpeedButton;
+ SpeedButton16: TSpeedButton;
+ SpeedButton17: TSpeedButton;
+ SpeedButton18: TSpeedButton;
+ SpeedButton19: TSpeedButton;
+ SpeedButton20: TSpeedButton;
+ SpeedButton21: TSpeedButton;
+ SpeedButton22: TSpeedButton;
+ Edit1: TEdit;
+ PM110: TMenuItem;
+ Image1: TImage;
+ UseOldCaseLb: TLabel;
+ PM111: TMenuItem;
+ SmoothCB: TCheckBox;
+ ISB_BW: TImageScrollBox;
+ N1: TMenuItem;
+ N2: TMenuItem;
+ ISB1: TImageScrollBox;
+ Label3: TLabel;
+ LogFile1: TLogFile;
+ ScanGrayCB: TCheckBox;
+ AttFileGB: TGroupBox;
+ AttListBox: TListBox;
+ Panel20: TPanel;
+ AddAttFileLB: TLabel;
+ DelAttFileLB: TLabel;
+ Splitter2: TSplitter;
+ Panel17: TPanel;
+ TreeView1: TTreeView;
+ Panel13: TPanel;
+ PrtLb: TLabel;
+ CaseHelpBtn: TBitBtn;
+ HTTPSClient: TElHTTPSClient;
+ Button5: TButton;
+ FTPSClient1: TElSimpleFTPSClient;
+ Button6: TButton;
+ procedure ActiveFormCreate(Sender: TObject);
+ procedure Panel9Resize(Sender: TObject);
+ procedure ISB1Click(Sender: TObject);
+ procedure WNoteBtnClick(Sender: TObject);
+ procedure CaseHelpBtnClick(Sender: TObject);
+ procedure FC0Click(Sender: TObject);
+ procedure FC1Click(Sender: TObject);
+ procedure FC2Click(Sender: TObject);
+ procedure FC3Click(Sender: TObject);
+ procedure FC4Click(Sender: TObject);
+ procedure FC5Click(Sender: TObject);
+ procedure FC6Click(Sender: TObject);
+ procedure PrePageBtnClick(Sender: TObject);
+ procedure NextPageBtnClick(Sender: TObject);
+ procedure OptionBtnClick(Sender: TObject);
+ procedure SelectScanBtnClick(Sender: TObject);
+ procedure mode1Click(Sender: TObject);
+ procedure mode2Click(Sender: TObject);
+ procedure mode3Click(Sender: TObject);
+ procedure mode4Click(Sender: TObject);
+ procedure N51Click(Sender: TObject);
+ procedure ScrollBar1Change(Sender: TObject);
+ procedure ISB1EndScroll(Sender: TObject);
+ procedure ISB1ImageMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure ISB1ImageMouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+ procedure ISB1ImageMouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure PM508Click(Sender: TObject);
+ procedure PM401Click(Sender: TObject);
+ procedure PM402Click(Sender: TObject);
+ procedure PM403Click(Sender: TObject);
+ procedure PM404Click(Sender: TObject);
+ procedure TreeView1Click(Sender: TObject);
+ procedure NewScanBtnClick(Sender: TObject);
+ procedure AddScanBtnClick(Sender: TObject);
+ procedure PageLVClick(Sender: TObject);
+ procedure PageLVKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure PageLVMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure PM101Click(Sender: TObject);
+ procedure PM104Click(Sender: TObject);
+ procedure PM102Click(Sender: TObject);
+ procedure PM103Click(Sender: TObject);
+ procedure PM106Click(Sender: TObject);
+ procedure PM107Click(Sender: TObject);
+ procedure PM108Click(Sender: TObject);
+ procedure PM109Click(Sender: TObject);
+ procedure PM301Click(Sender: TObject);
+ procedure PM302Click(Sender: TObject);
+ procedure PM303Click(Sender: TObject);
+ procedure PM501Click(Sender: TObject);
+ procedure PM502Click(Sender: TObject);
+ procedure PM503Click(Sender: TObject);
+ procedure PM504Click(Sender: TObject);
+ procedure PM505Click(Sender: TObject);
+ procedure PM510Click(Sender: TObject);
+ procedure PM509Click(Sender: TObject);
+ procedure PM507Click(Sender: TObject);
+ procedure PopupMenu1Popup(Sender: TObject);
+ procedure PopupMenu4Popup(Sender: TObject);
+ procedure PopupMenu5Popup(Sender: TObject);
+ procedure SampleScanBtnClick(Sender: TObject);
+ procedure StatusBar1DblClick(Sender: TObject);
+ procedure ExportBtClick(Sender: TObject);
+ procedure ImportBtClick(Sender: TObject);
+ procedure HTTPSClientCertificateValidate(Sender: TObject;
+ X509Certificate: TElX509Certificate; var Validate: Boolean);
+ procedure ScanDuplexCBClick(Sender: TObject);
+ procedure CheckCaseBtnClick(Sender: TObject);
+ procedure Timer1Timer(Sender: TObject);
+ procedure Timer2Timer(Sender: TObject);
+ procedure TransBtnClick(Sender: TObject);
+ procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
+ procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+ procedure TreeView1KeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure ViewModeBtnMouseEnter(Sender: TObject);
+ procedure Button3Click(Sender: TObject);
+ procedure AddCredit1RGClick(Sender: TObject);
+ procedure CB1Click(Sender: TObject);
+ procedure Button4Click(Sender: TObject);
+ procedure ISB1Enter(Sender: TObject);
+ procedure TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+ procedure PM601Click(Sender: TObject);
+ procedure PopupMenu6Popup(Sender: TObject);
+ procedure PM604Click(Sender: TObject);
+ procedure PM605Click(Sender: TObject);
+ procedure SpeedButton3Click(Sender: TObject);
+ procedure SpeedButton14Click(Sender: TObject);
+ procedure SpeedButton15Click(Sender: TObject);
+ procedure SpeedButton16Click(Sender: TObject);
+ procedure SpeedButton17Click(Sender: TObject);
+ procedure SpeedButton18Click(Sender: TObject);
+ procedure SpeedButton19Click(Sender: TObject);
+ procedure SpeedButton20Click(Sender: TObject);
+ procedure SpeedButton21Click(Sender: TObject);
+ procedure SpeedButton22Click(Sender: TObject);
+ procedure ActiveFormKeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure PM110Click(Sender: TObject);
+ procedure PM602Click(Sender: TObject);
+ procedure PrtLbClick(Sender: TObject);
+ procedure Panel1DblClick(Sender: TObject);
+ procedure Panel11DblClick(Sender: TObject);
+ procedure UseOldCaseLbClick(Sender: TObject);
+ procedure PM111Click(Sender: TObject);
+ procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
+ procedure SmoothCBClick(Sender: TObject);
+ procedure N1Click(Sender: TObject);
+ procedure TreeView1MouseEnter(Sender: TObject);
+ procedure ScrollBox1MouseEnter(Sender: TObject);
+ procedure ScanGrayCBClick(Sender: TObject);
+ procedure AddAttFileLBClick(Sender: TObject);
+ procedure DelAttFileLBClick(Sender: TObject);
+ procedure AttListBoxDblClick(Sender: TObject);
+ procedure AttListBoxClick(Sender: TObject);
+ procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure HTTPSClientRedirection(Sender: TObject; const OldURL: string;
+ var NewURL: string; var AllowRedirection: Boolean);
+ procedure Button5Click(Sender: TObject);
+ procedure Button6Click(Sender: TObject);
+ private
+ { Private declarations }
+ HotKeyId1,HotKeyId2,HotKeyId3,HotKeyId4 :Integer;
+
+ ////////傳入參數/////////
+ FUrl : String;
+ FCaseID : String;
+ FMode : String; //NSCAN:新件;ESCAN:修改 20170306 DSCAN:被配合待掃瞄清單使用
+ FModeName : String;
+ FWork_no : String;
+ FUserID : String;
+ FUserName : String;
+ FUserUnit : String;
+ FData : String;
+ FVerify : String;
+ FReWrite : String;
+ FLanguage : String;
+ FLoanDoc_Value : String; //新增授信卷的值
+ FLoanDoc_Enable : String; //新增授信卷是否可異動
+ FUseProxy : String; //是否使用Proxy
+ FC_DocNoList : String; //外面傳來要新增的文件編號
+ FC_DocNameList : String; //外面傳來要新增的自訂文件
+ FFixFileList : String; //要鎖住的檔名
+ FIs_In_Wh : String; //是否只顯示入庫文件 (Y:只顯示入庫 N:只顯示非入庫 空白:都顯示)
+ FOldCaseInfo : String; //舊件資訊 CaseID_year[tab]CaseID_year
+ FPrintyn : String; //是否可列印
+ FIs_OldCase : String; //是否是舊案第一次進入
+ FCustDocYN : String; //是否可自訂文件
+ //20170222 新增
+ FImgDPI:integer;//DPI 依業務別決定 150~~1200 預設300
+ FScanColor:integer;///掃瞄色彩 依業務別決定 0 :黑白 1:灰階 2:彩色 預設黑白
+ FFileSizeLimit:integer;//匯入單一檔案大小限 依業務別決定 以KB為單位 預設5*1024kb
+ FCaseNoLength:integer;//案件編號長度檢查 依業務別決定 無預設 一定要傳入
+ FImgDelete:string; // Y/N 有權限可在補件時刪除影像
+ FIsExternal:string;//Y/N
+ FCheck_main_form:string; //Y/N
+ FWH_category:string; //Y/N Y是歸類時有區分入庫非入庫文件 N 是不區分
+ ////////傳入參數///////
+
+ TransMode : TTransMode; //用何種方式上傳檔案
+ //********Http參數********
+ HttpErrStr : String; //錯誤訊息
+ //********Http參數********
+
+ //********Ftp參數*********
+ FFtpIP : String;
+ FFtpID : String;
+ FFtpPwd : String;
+ FFtpRootPath : String;
+ FFtpExtraPath : String;
+ FFtpPort : Integer;
+ FFtpProtocol : TFtpProtocol;
+ //********Ftp參數*********
+
+ //********ini參數********
+ DeviceDelete : Boolean; //空白頁刪除啟動
+ DeviceDeleteSize : Integer; //空白頁Size
+ ScannerReverse : Boolean; //是否需反相
+ BoardClear : Boolean; //是否清黑邊
+ ScanDpi : Integer; //掃瞄DPI
+ ScanDuplex : Boolean; //是否雙面掃瞄
+ ScanRotate : Integer; //掃瞄時旋轉角度
+ ScanDeskew : Boolean; //是否傾斜矯正
+ ScanBright : Integer; //亮度
+ ScanContrast : Integer; //對比
+ ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
+ ScanImgSetUse : Boolean; //是否使用亮度對比設定
+
+ //********ini參數********
+ ScanColor : TImageFormat;
+
+ //********時間********
+ ServerDate : String;
+ ServerTime : String;
+ Balance : Longint; //local跟server的時間差
+ ScanDenialTime : String; //停止進件時間
+ //********時間********
+ ScanDenialHint : String; //掃描顯示提醒字串
+
+ //********路徑********
+ ScanPath : String; // SpecifyDir\Workid\userunit\mode
+ ImagePath : String; // SpecifyDir\Workid\userunit\mode
+ ImageSavePath : String; // ImagePath\
+ ScaniniPath : String; // SpecifyDir\Workid\userunit\
+ LngPath :String; //多國語言檔目錄
+ CheckXmlPath : String; //檢核用的Xml存放目錄
+ SitePath : String; //登打位置(切簽名用)
+ SamplePath : String; //範本目錄
+ TransPath : String; //檔案上傳的路徑(補充件會多一層目錄)
+ //********路徑********
+ ScanSaveFilename : String; //掃瞄的檔名
+ ScanCaseno : String; //掃瞄時的案號
+ ScanDocDir : String; //掃描時的文件代號目錄
+ //********清單區********
+ Doc_Inf_List : TStringList; //Doc_Inf 清單
+ DM_FORM_INF_List :TstringList; //DM_FORM_INF 清單
+ FORM_INF_List : TStringList; //FORM_INF的清單
+ CHECK_RULE_INF_List : TStringList; //CHECK_RULE_INF 清單
+ MEMO_INF_List : TStringList; //MEMO_INF 清單
+ WORK_INF_List : TStringList; //WORK_INF 清單
+ LASTEST_FORM_INF_List : TStringList; // LASTEST_FORM_INF 清單
+
+ FindResult : TStringList; //找SQLData的結果
+ CaseList : TStringList; //記錄掃瞄案件的順序
+ Context_DocnoList : TStringlist; //案件裡的Docno清單
+ CaseDocNoList : TStringlist; //案件裡的DocNo清單(不重複)
+ CaseDocNo_CopiesList : TStringlist; //案件裡的DocNo份數清單
+ ContextList : TStringlist; //案件裡的檔案清單
+ AttContextList : TStringlist; //案件裡的附加檔案清單
+ OMRFileList : TStringList; //要OMR檢核的文件(只檢查每種Form的第一頁)
+ Cust_DocNoList : TStringlist; //自行定義文件名稱
+ IN_WH_DocNoList : TStringlist; //入庫的文件清單
+
+ FormCode_PageSize : TStringList; //文件的預設大小 FormCode_Height_Width
+ DocNo_NeedDoc : TStringList; //有Docno時要相依的文件 DocNo_相依文件_相依文件
+ DocNo_NoDoc : TstringList; //有Docno時互斥的文件 DocNo_互斥文件_互斥文件
+ DocNo_VerinCase : TStringlist; //案件裡的DocNo+版本的清單
+
+ NoSaveBarCodeList : TStringlist; //不儲存的條碼清單
+ FormID_List : TStringlist; //FormID 清單 20130403 因為原FormCode2Docno會很慢..把FormID抽出來
+ DocNo_List : TStringlist; //DocNo 清單 20130403 因為原FormCode2Docno會很慢..把DocNo抽出來
+ NowShowFileList : TStringlist; //目前顯示的影像清單
+ NowSelectFileList : TStringlist; //目前被點選的影像清單
+ GuideFormIDList : TStringlist; //要當導引頁表單清單
+ DivPageFormIDList:TStringlist; //要當分案頁表單清單
+ LastInitFormidList:TStringList;
+ LastAddFormidList:TstringList;
+ SampleFormIDList:TStringList; //20170627 已存在範本的formid
+ ExistImgList:TStringList; //20170724 已經存在的影像list for ESCAN //Img的完整路徑
+ reSizeExistImgList:TstringList; //20171012被縮放的舊圖MD5存入
+ //********清單區********
+
+ //********顯示區********
+ NowCaseno : String; //目前顯示的案件編號
+ NowDocNo : String; //目前的文件編號
+ NowDocDir : String; //目前的文件目錄
+ NowFormCode : String; //目前顯示的表單編號
+ NowFormName : String; //目前顯示的表單名稱
+ NowPage : Integer; //目前點選的頁碼
+ DisplayPath : String; //目前顯示的目錄
+ //********顯示區********
+
+ //******索引資料*********
+ Case_loandoc : String; //是否新增授信卷
+ //******索引資料*********
+
+ //********十字定位點資訊********
+ UpLPoint : Tpoint; //左上方的十字點
+ UpRPoint : Tpoint; //右上方的十字點
+ DownLPoint : Tpoint; //左下方的十字點
+ DownRPoint : Tpoint; //右下方的十字點
+ Point_Width : String; //十字點的寬
+ Point_Height : String; //十字點的高
+ //********十字定位點資訊********
+
+ CaseIDLength : Integer; //案件編號長度
+ FormIDLength : Integer; //FormID長度
+ DocNoLength : Integer; //Docno長度
+
+ PEFileName : String; //掃描時的檔名
+ DownFileErrStr : String; //下載影像時發生的錯誤
+
+ ISB : TImageScrollBox;
+ ScanInfo : TScanInfo;
+ TwainShowUI : Boolean;
+ MpsBarcodeinf : TMpsBarcodeinf;
+ ScanMode : TScanMode;
+ Mpskey : String;
+ Seg : Integer; //顯示的邊界值
+ VMode : Integer; //顯示的index
+ NowClick : Integer; //目前點到的按鈕功能Index
+ ScanIP : String; //掃瞄端的IP
+ DisplayISB : TImageScrollBox; //被點到的影像
+ SelectISB : TImageScrollBox; //被點到的縮圖
+ SelectPage : Integer; //被點到的頁數
+ NewTreeNode,MyTreeNode1,MyTreeNode2,MyTreeNode3 : TTreenode;
+ InitialOk : Boolean; //資訊載入是否完成
+ ShowText : String; //DataLoading時要秀出的訊息
+ Ext : String; //附檔名 .tif .jpg
+ SafePixel : Integer; //OMR容忍誤差值點數
+ OMRErrInfo : Array[1..11] of TOMRErrInfo; //檢核的方式及訊息
+ ScrollRec : Array[1..8] of TScrollRec; //瀏覽窗的Scroll記錄
+ RecHozPos,RecVerPos : Integer; //記錄MPSViewX1的ScrollBar位置
+ ReczoomPercent : Single;
+ SortMode : Boolean;
+ PreMytreeNode2Name:String;
+ HS,VS : Integer;
+ iRate : Single;
+ Bt : Integer; //去直線時橫線判斷的容忍值
+ BarCodeRotate : Integer; //條碼要轉的角度
+ HaveAppDoc : Boolean; //補全時是否有補入要保書
+ PageLVclear : Boolean;
+ CaseCount,PageCount : Integer; //總案件量及總頁數
+ Item : TMenuItem;
+ SampleAnchorMode : String; //範本掃瞄十字線的模式 NONE:無;ANCHOR:十字;FRAME:邊框
+ DownImgStatus : String; //下載影像的狀態(NO_DATA:沒資料;NO_FILE:沒影像)
+ TransForm_Field : String; //要用OMR勾選確認是否轉換FORMID的欄位名稱
+ NowWork_No : String; //現在的作業別
+ CropBarcode : String; //要切影像的條碼
+ Has_Authorize :String; //是否有授權書影像
+ AttName : String; //未歸類目錄名稱
+ NowGuideFormID : String;
+ NowDivPageFormID:String;
+
+ FirstDocDir : String;
+ FMaxUploadSize:String;// 上傳zip大小限制
+ FJpgCompression:integer;// 20171211 jpg to tif 的壓縮率
+
+ Draging : Boolean;
+ MDown : Boolean; //20181210 用來判斷滑鼠右鍵要Popupmenu是否有MouseDonw發生
+
+ FEvents: ICB_IMGPSScanXEvents;
+
+ procedure HotKeyDown (var Msg : TMessage);message WM_HOTKEY;
+ Procedure InitialLanguage(Sender: TObject); //畫面載入多國語言
+ //Function _Msg(S:String):String;
+
+ //*********SQL相關************
+ Procedure SetSQLData(ColumeStr:String;FromList,ToList:TStringlist); //把SQL值塞入
+ Function GetSQLData(TableList:TStringlist;Colname:String;colNo:Integer):String; //依欄位及索引取值
+ Function FindSQLData(TableList:TStringlist;ColumeStr,KeyColumeStr,KeyStr:String;ColNo:Integer;Var ResultList:TStringlist):Boolean; //找指定的資料
+ Function GetFindResult(Col:String):String;
+ //*********SQL相關************
+
+ //*********FTP相關************
+ Function GetFtpinfo(CaseID,Action:String):Boolean;
+ Procedure SetFtpInfo; //餵入FTP資訊
+ Function FtpCaseComplete(SendData:String):Boolean;
+ //*********FTP相關************
+
+ //*******轉換區*********
+ Function FindDivFormCode(FormCode:String):Boolean; //找有沒有分案的條碼
+ Function FormCode2FormName(CaseID,FormCode:String):String; //用FormCode轉成文件名稱
+ Function FormCode2FileName(FormCode:String;List:TStrings):String; //用FormCode找出檔名(第一頁)
+ Function FileName2FormCode(FileName:String):String; //從檔名取出FormCode
+ Function FileName2FormName(CaseID,FileName:String):String; //從檔名取出文件名稱
+ Function FileName2ScanPage(FileName:String):Integer; //從檔名取出掃瞄頁數
+ Function FileName2NoQuene_Filename(FileName:String):String; //取出沒有序號的檔名
+ Function FileName2Index(FileName:String):Integer; //從檔名取出在ContextList的序號
+ Function FileName2NowDcoNo(FileName:String;CtList,DNList:TStrings):String; //從檔名取出歸屬的文件代號
+ Function FormCode2DocNo(FormCode:String):String; //FormCode轉Docno
+ Function FormCode2Version(FormCode:String):String; //FormCode轉版本
+ Function FormCode2Page(FormCode:String):String; //FormCode轉文件頁數
+ Function DocNo2DocName(CaseID,DocNo:String):String; //Docno轉Doc名稱
+ Function DocNo2FileName(DocNo:String;List:TStrings):String; //用DocNo找出檔名(第一頁)
+ Function FormCode2WorkNo(FormCode:String):String; //用FormCode取出作業別
+ Function DocNo2WorkNo(DocNo:String):String; //用DocNo取出作業別
+ Function DocNo2DocNoDir(Path,DocNo:String):String; //DocNo轉成DocNo(份數)目錄
+ Function DocNoDir2DocNo(DocNoDir:String):String; //DocNo(份數)目錄轉成DocNo
+ Function DocNoDir2Index(Path,DocNoDir:String):Integer; //DocNo(份數)目錄轉成index
+
+ Function DocNoNeedDiv(DocNo:String):Boolean; //是否是需分份數的文件代號
+ //Function CaseNo2DocNo(CaseNo:String):TStringList;
+
+ Function CaseNode2Info(Node:TTreeNode;Mode:Char):String; //案件Node取案件編號 Mode: I:Caseno;P:Page
+ Function DocNode2Info(Node:TTreeNode;Mode:Char):String; //文件Node取文件代號 Mode: I:Docno;N:Docname;P:Page;G:Group
+ Function FormNode2Info(Node:TTreeNode;Mode:Char):String; //表單Node取表單代號 Mode: I:FormID;N:FormName;P:Page
+ //*******轉換區*********
+
+ Procedure PriorPage(Page:Integer); //上一頁
+ Procedure NextPage(Page:Integer); //下一頁
+
+ Function DocNoExistsinTree(CaseNode:TTreeNode;DocNo:String):Boolean; //DocNo是否己存在樹裡
+ Function DocnoNeedGroup(DocNo:String):Boolean; //傳入的DocNo是否需分組
+
+ function GetSiteOMR(FileName, Site: String;bt: Integer): Integer;
+ Function FindISB2View(Vmode:Integer):TImageScrollBox; //找空的ISB來顯示
+ Procedure R_W_ScanIni(Mode:Char); //'R'讀取;'W'寫入
+ Procedure GetDefScanIni; //取得掃瞄的預設值
+ procedure DesableImage;
+ procedure EnableImage(v:integer;Sender : TObject);
+ Procedure ViewMouseMode(v:Integer);
+ Procedure GoViewMode;
+ Procedure DisplayMode(index,H_Count,W_Count:Integer;BasePanel:TPanel);
+ Function GetServerDate : Boolean; //取主機時間
+ Function GetSetInf1 : Boolean; //取系統設定資訊mode1 DOC_INF
+ Function GetSetInf2 : Boolean; //取系統設定資訊mode2 DM_FORM_INF
+ Function GetSetInf3 : Boolean; //取系統設定資訊mode3 FORM_INF
+ Function GetSetInf4 : Boolean; //取系統設定資訊mode4 CHECK_RULE_INF
+ Function GetSetInf5 : Boolean; //取系統設定資訊mode5 MEMO_INF
+ Function GetSetInf6 : Boolean; //取系統設定資訊mode6 WORK_INF
+ Function GetSetInf7 : Boolean; //取系統設定資訊mode7 LASTESTFORM_INF
+ Procedure SetFormID_DocNo; //將FormID及Docno抽出來另存入list裡
+ Procedure SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
+
+ Procedure DataLoading(Loading,UseTimer:Boolean); //資料載入中要停止點選的動作
+ procedure ClearView(stkv:Integer); //清除瀏覽窗的影像
+ Function DrawDocItem2(CaseNode : TTreenode;Caseno:String):Boolean; //畫出文件名稱的Tree
+
+ Procedure initkscan; //檢查掃描器的功能
+ procedure LoadImgFile; //載入案件
+ procedure LoadImgFile1; //載入案件
+ procedure LoadAttFile(CaseID:String); //載入附加檔案
+ Procedure DistinctFormCode(CaseID:String); //案件裡的FormCode取出第一頁
+ Function OMRCheckCase(CaseID:String):Boolean; //OMR檢核
+ Procedure OMRErr2ini(CaseID,Reason,FileName,Site,RelaFileName,RelaSite,Anchor,Anchor1:String;Del,Ingnore,Display:Boolean); //OMR檢核失敗寫入ini
+ Procedure OMRErrini2List(CaseID:String;ErrlistForm : TErrlistForm); //OMR檢核失敗從ini寫入ListView
+ Function DownLanguage:Boolean; //下載多國語言檔
+ Function FindMpsView(Vmode:Integer):TImageScrollBox;
+ Function CaseAsk(CaseID:String):Integer; //詢問是否可上傳 (-1:失敗;0:可以;1:不行;)
+ Function CaseComplete(Path,CaseID:String;MainCase:Boolean):Boolean; //通知傳送完成
+ Function GetCaseFormID(Path:String):String; //取案件的FormID
+ Procedure CreateFormID_FormName(Path,CaseID:String); //產生FormID_FormName.dat
+ Procedure CreateDocNo_DocName(Path,CaseID:String); //產生DocNo_DocName.dat
+ Procedure CreateIn_WH(CaseID:String); //產生In_WH.dat
+ Function CreateDocNo_Info(CaseID:String):String; //產生保管袋文件 DocNo[tab]份數[tab]總頁數[tab]是否異動[換行]DocNo[tab]份數[tab]總頁數[tab]是否異動
+ Function CreateCustDocNo_Info(CaseID:String):String; //產生自訂文件 DocName[tab]份數[tab]總頁數[tab]是否異動[#13#10]DocName[tab]份數[tab]總頁數[tab]是否異動
+ //Function CreateCustDocNo_Info(path,CaseID:String):String; overload
+ Function CreateAttach_Info(CaseID:String):String; //產生是否有Attach Y:有 N:沒有
+ Function CreateDocnoFrom_Info(CaseID:String):String; //產生被引進的保管袋文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+ Function CreateCustDocNoFrom_Info(CaseID:String):String; //產生被引進的自定文件資訊 Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
+
+ Function GetDocNoEdit(CaseID,DocNo,DocName:String):String; //取出DocNo是否被異動 (Y/N)
+ Function GetDocNo_Count(Path,DocNo:String):Integer; //取出文件份數
+ Function GetDocNo_Page(Path,DocNo:String):Integer; //取出文件總頁數
+ Function FormIDExists(FormCode:String;CheckDate:Boolean;index:Integer):Boolean; //檢查FormID是否存在及是否要檢查啟用停用日期
+ Function Case_DocNoExists(CaseID,Docno:String):Boolean; //Docno是否存在案件裡
+ Procedure ReSortFileName_New(Path:String); //檔名重新排序
+ Procedure ReSortFileName(Path:String); //檔名重新排序
+ Procedure ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
+ Function GetOMRCheckSet:Boolean; //下載OMR檢核XML檔
+ Function GetKeyinSet : Boolean; //取登打設定
+ Procedure CheckRule2OMRErrInfo; //檢核規則填入OMRErrINFo Record
+ Procedure ReNameContext(Path,OldName,NewName:String);
+ Procedure DeleteImageFile(Path,FileName,CaseID:String); // 刪除檔案
+ Procedure DeleteFormCodeFile(CaseID,DocDir,FormID:String); //刪除指定FormID文件
+ Function DeleteDocNoFile(Path,DocNo:String):Boolean; //刪除指定DocNo文件
+ Procedure DeleteShowFile(Path:String); //刪除顯示中的影像
+ Function GetDataDocNoPage(MainDocNo,MainVersion:String):Integer; //取記錄的文件_版本頁數
+ Function CheckCaseDocNoPage(CaseID,DocNo,Version:String;Pages:Integer):Integer; //檢查案件裡的文件_版本頁數
+ Function FindFormCodePages(CaseID,FormCode:String):Integer; //計算案件裡FormID的頁數
+ Function GetDataFormCodePages(FormCode:String):Integer; //取記錄的FormcID的頁數
+ Procedure CaseReSize(CaseID:String); //案件的影像縮放
+ Procedure ImageReSize_FormID(CaseID,FileName:String); //依十字定位點做縮放
+ Procedure ImageReSize_tmp(FormID,FileName:String); //依十字定位點做縮放(暫存檔)
+ Function TransCaseID(Path,CaseID:String;MainCase:Boolean):Boolean; //傳送案件
+ Procedure NewTreeNodeRefresh;
+ Procedure MyTreeNode1Refresh;
+ Procedure MyTreeNode2ReFresh(CaseID:String);
+ Procedure MyTreeNode3ReFresh(CaseID:String);
+ Function Node2DocNo(Node2:TTreeNode):String; //MyTreeNode2取DocNo出來
+ Function Node3DocNo(Node3:TTreeNode):String; //MyTreeNode3取DocNo出來
+ Function Node3FormID(Node3:TTreeNode):String; //MyTreeNode3取FormCode出來
+ Function GetNode2Name(Node2:TTreeNode):String; //取MyTreeNode2的識別字出來(記之前點選用)
+ //Function Down_Replace_Img(SPAth,DPath,CaseID:String):Boolean;
+ Function DownLoadImage(Path,CaseID:String):Boolean;
+ Function Down_Img(Path,CaseID:String):Boolean;
+ Function GetNoNameCase(Path:string):String; //取未配號XXXX
+ Procedure CaseResort(Path:String); //案件的檔案重新排序(次文件依Docno挑)
+ Procedure CaseResort2Scanlist(Path:String); //案件的檔案重新排序給scanlist(次文件依FormID排)
+ Procedure DistinctDocinCase(Path:String); //列出案件裡的Docno_版本
+ Procedure DistinctDocNoinCase(Path:String); //列出案件裡的Docno
+ Procedure ClearErrini(CaseID:String;CaseNode:TTreeNode); //清掉檢核檔案
+ Procedure SetCaseList(Mode:Char;Index:Integer;text:String); //'A:加入,I:插入,D:刪除,E:修改'
+ Procedure SetDocNoList(Mode:Char;Index:Integer;CaseNo,DocDir,Copies:String); //'A:加入,I:插入,D:刪除,E:修改'
+ Procedure SetContextList(Mode:Char;Index:Integer;CaseNo,DocDir,FileName:String); //'A:加入,I:插入,D:刪除,E:修改'
+ Procedure SetAttContextList(Mode:Char;Index:Integer;CaseNo,FileName:String); //'A:加入,I:插入,D:刪除,E:修改'
+
+
+ Function checkCaseOMRDone:Boolean; //檢查案件是否完成OMR檢核
+ Function CheckCaseID_OK:Boolean; //檢查是否有未配號的案件
+ Procedure CreateEmptyCase(Path,CaseID:String); //產生空白案號(重掃件用)
+ Procedure InitScrollRec; //初始化影像Scroll記錄
+ Procedure GetScrollData(ISB:TImageScrollBox;Var HS,VS:Integer;Var iRate:Single); //取影像Scroll記錄
+ Procedure SetScrollData(ISB:TImageScrollBox;HS,VS:Integer;iRate:Single); //寫影像Scroll記錄
+ Procedure FormIDReplace(CaseID,DocDir,OldFormID,NewFormID:String); //指定FormID更換成新的FormID
+ Procedure ShowFileReplace(Path,NewFormID:String);//顯示的影像換成新的FormID
+ Procedure PageReplaceFormID(Path,NowFormID,NewFormID:String); //選取頁更換FormID
+ Function ModeNeedCheck(OMRMode,ScanMode:String):Boolean; //掃瞄模式是否要做檢核
+ procedure WMMOUSEWHEEL(var message: TWMMouseWheel); message WM_MOUSEWHEEL;
+ Function GetCasePage(Path,CaseID:String):Integer;
+ Function GetFormIDPage(FileList:TStringlist;FormID:String):Integer;
+ Procedure SetFile2Case(CaseID,FileName:String);
+ Procedure WriteResize(ImgName,TxtName:String); //產生Resize.dat
+ Function GetCase_PageCount(var CaseCount,PageCount:Integer):Boolean; //取出案件的數量及頁數 ID為空值時為取所有的
+ Function BarCode2FormID : String; //Barcode依規則轉成FormID
+ Function BarCode2CaseID : String; //Barcode依規則轉成CaseID
+ Procedure WriteCaseIndex(Path:String);
+ Procedure ReadCaseIndex(Path:String);
+ Procedure ClearCaseIndex;
+ Procedure GetSelectImageFile;
+ Function GetDocNoDir(Path,DocNo:String):String; //取出目前DocNo的份數
+ Function CheckFormIDExists(DocNoNode:TTreeNode;FormID:String):Boolean; //檢查FormID是否存在文件裡
+
+ Procedure ZipMainFile(SoPath,DePath,ZipName:String); //壓縮影像檔
+ Procedure ZipMaskFile(SoPath,MarkPath,DePath,ZipName:String); //壓縮遮罩影像檔
+ Procedure ParserPoint(S:String); //解析十字點的字串
+ Function CheckScanDenialTime:Boolean;
+ Function FormID2Anchor(FormID:String):String; //用FormID取出十字模式
+ Function Index2Anchor(Anchor:String):String; //十字模式 0->NONE;1->ANCHOR;2->FRAME
+ Function MemoInfoTransfer(Mode,Str:String;ID_S,Name_S:TStringlist):String; //註記代碼註記類別轉換 Mode 'ID':代碼轉名稱;'NAME':名稱轉代碼
+ Function GetFormatID(CaseID:String):String; //取出案件的FormatID
+ Function FindNoSaveBarCode : Boolean; //找是否有不要儲存影像的條碼
+ Function CheckAvailable:Boolean; //檢查是否可使用元件
+ Function Case2Mask(SoPath,DePath:String):Boolean;//產生遮罩影像
+ Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
+ Function GetNewCustomDocNo(Path,DocName:String):String; //取出未使用的自訂文件代號
+ Function GetCustomDocName(Path,DocNo:String):String; //取出自定文件名稱
+ Function GetCustomFormID(Path,DocNo:String):String; //取出自定文件FormID
+ Function GetCustomDocDir(Path,DocName:String):String; //取出自定文件DocDir
+ Function FindCustomDocName(Path,DocName:String):Boolean; //尋找自定文件名稱是否存在
+ Procedure DeleteCustomDocDir(Path,DocNo:String); //刪除自定文件DocNo
+ Function CheckFormID_Prt(FormID:String):Boolean; //傳入的FormID是否預設列印
+ procedure PrintImg(FileName, LoginID, Datetime,Path: WideString);
+ Function FindLastestDocDir(CaseID,DocNo:String):String; //找出最新的DocDir
+ Procedure Create_Cust_DocDir(CaseID:String); //產生外面傳入的文件代號及自定文件
+ Procedure OldCasetoNewCase(CaseID:String); //將舊案份數轉成新規則
+ Procedure ErrFormtoCurrentForm(CaseID,EFormID,CFormID:String);//將舊案的錯誤FormID改正確的FormID
+ Procedure SetRecordEditedDocDir(Mode:Char;CaseID,DocDir:String); //記錄被異動的文件目錄 'A:加入D:刪掉'
+ Function GetDocDir_Page(CaseID,DocDir:String):Integer; //取得DocDir的頁數
+ Function Path2DocDir(Path,CaseID:String):String;
+ Function GetDocNo_IS_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
+ Procedure SortDocDir_FormID(CaseID,DocDir:String); //將DocDir裡的文件編號排序
+ Procedure GotoAttach(OldLevel:Integer);
+ Function DocNoIs_In_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
+ Procedure CreateCaseNeedData(Path:String); //先做影像截取會少二個文字檔,產生CaseDocNo.dat及DocDir.dat
+ Procedure SetDocDirtoSelected(CaseNode:TTreeNode;DocDir:String);
+ Function CheckSelectImg_UseCase(Path,CaseID:String):Boolean; //檢查選擇的影像是否有包含被引用的影像
+ Function TransOldCaseFile(Path:String):Boolean; //上傳引用舊件的記錄檔
+ Function Writelog(CaseID:String):Boolean;
+ Function FormIDAppear(FormID:String):Boolean; //FormID是否可出現
+ Function DocNoAppear(DocNo:String):Boolean; //DocNo是否可出現
+ Function GetDocNoCount(CaseID,DocNo:String):Integer; //取DocNo數量
+ Function GetDocDirCopies(CaseID,DocDir:String):Integer; //取DocDir份數
+ Procedure SetDocDirCopies(CaseID,DocDir:String;NewCopies:Integer); //修改DocDir份數
+ Function GetDocDirCopies_Rec(Path,CaseID,DocDir:String):Integer; //取記錄裡的DocDir份數
+ Function GetCustomNameCount(CustomName:String):Integer; //取外傳的名稱數量
+ Function GetCustomDocNoCount(Docno:String):Integer; //取外傳的DocNo數量
+ Function ISGuideFormID(FormID:String):Boolean;
+ Function CaseDelete_Enable(CaseID:String):Boolean; //案件可否被刪除
+
+ Procedure MoveImage(Path:String;mp:Integer); //移動頁數
+ Procedure MoveImage_Drag(Path:String;fp,tp:Integer); //拖拉移動頁數
+
+
+ Procedure SetUseCase(Mode:Char;Path,DocDir,FormCaseID,ToCaseID:String); //記錄引用其他案件 A:加入 D:刪掉
+ Function GetUseCase(Mode:Char;Path,DocDir:String):String; //F:取被引用 To:引用
+
+ Procedure Case2upload(CaseID:String);
+ Procedure Download2Case(SoDir,DeDir:String);
+
+ procedure view_image_FormCode(Path,FormCode:String;stpage,stview:integer); //用FormCode來找影像
+ procedure view_image_DocNo(Path,DocNo,FormID:String;Pages:integer); //用DocNo來找影像
+
+ Function ShapeName2PreViewISBName(SP:TShape):String; //轉出指定PreViewISBName
+ Procedure CreatePreViewISB(Count:Integer);
+ Procedure FreePreViewISB;
+ Procedure FitPreViewISB;
+ Procedure PaintShape(FromImg,ToImg:TImageScrollBox); //畫有被選取的影像
+ Procedure FreeShapeobj(SelectISB : TImageScrollBox);
+ Procedure ISBClick(Sender : TObject);
+ Procedure ISBMouseMove(Sender: TObject; Shift: TShiftState;
+ X, Y: Integer);
+ procedure ISBImageMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure ISBImageMouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure ISBEndDrag(Sender, Target: TObject; X, Y: Integer);
+ procedure ISBDragDrop(Sender, Source: TObject; X, Y: Integer);
+ procedure ISBDragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+
+ procedure BtnMouseEnter(Sender: TObject);
+
+ procedure PageEnd; //掃描接收完成
+ Procedure PageDone; //掃描完成後顯示影像
+ procedure StatrTwainScan;
+ procedure OnAcquire( const DibHandle : THandle;
+ const XDpi : Word;
+ const YDpi : Word;
+ const CallBackData : LongInt );
+
+
+ procedure ActivateEvent(Sender: TObject);
+ procedure ClickEvent(Sender: TObject);
+ procedure CreateEvent(Sender: TObject);
+ procedure DblClickEvent(Sender: TObject);
+ procedure DeactivateEvent(Sender: TObject);
+ procedure DestroyEvent(Sender: TObject);
+ procedure KeyPressEvent(Sender: TObject; var Key: Char);
+ procedure MouseEnterEvent(Sender: TObject);
+ procedure MouseLeaveEvent(Sender: TObject);
+ procedure PaintEvent(Sender: TObject);
+ function GetCurrentVersionNo: String;
+ procedure initParameter;
+ procedure LastInitFormidListCreate(path:string);
+ function checkFormCodeIsCustom(path,formcode:string):boolean;
+ function ISDivPageFormID(FormID: String): Boolean;
+ function GetSampleInf: Boolean;
+ procedure InitExistImgList(casepath:String);
+ function LoadFileGetMD5(const filename:string):string; //20170809 取的檔案的MD5
+ function ISExistImg(const filename:string):boolean; //20170809 確認是否存在原有影像
+ procedure _DelTreeForExistImg(ASourceDir:String); //2017 刪除前確認 有舊影像嗎
+ function DocNoIsExistImg(DocNopath: String): boolean; //2017 刪除前確認 有舊影像嗎
+ function CheckCaseAttach_OK: Boolean;
+ function DeleteDocNoFileForESCAN(Path, DocNo: String): Boolean; //2017 確認是否有未歸類文件
+ function CheckRequiredColumnValues(workno,caseno:String) :Boolean; //20171003 此大類下此案是否檢核必填
+ function logTimeString :String;
+ procedure ReduceLogFile ;
+ function FindLastestDocDirForPage(CaseID, DocNo, formid: String): String;
+ function OMRErrini2ListForLog(CaseID: String):String;
+ protected
+ { Protected declarations }
+ procedure DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage); override;
+ procedure EventSinkChanged(const EventSink: IUnknown); override;
+ function Get_Active: WordBool; safecall;
+ function Get_AlignDisabled: WordBool; safecall;
+ function Get_AlignWithMargins: WordBool; safecall;
+ function Get_AutoScroll: WordBool; safecall;
+ function Get_AutoSize: WordBool; safecall;
+ function Get_AxBorderStyle: TxActiveFormBorderStyle; safecall;
+ function Get_Caption: WideString; safecall;
+ function Get_Color: OLE_COLOR; safecall;
+ function Get_DockSite: WordBool; safecall;
+ function Get_DoubleBuffered: WordBool; safecall;
+ function Get_DropTarget: WordBool; safecall;
+ function Get_Enabled: WordBool; safecall;
+ function Get_ExplicitHeight: Integer; safecall;
+ function Get_ExplicitLeft: Integer; safecall;
+ function Get_ExplicitTop: Integer; safecall;
+ function Get_ExplicitWidth: Integer; safecall;
+ function Get_Font: IFontDisp; safecall;
+ function Get_HelpFile: WideString; safecall;
+ function Get_KeyPreview: WordBool; safecall;
+ function Get_MouseInClient: WordBool; safecall;
+ function Get_ParentCustomHint: WordBool; safecall;
+ function Get_ParentDoubleBuffered: WordBool; safecall;
+ function Get_PixelsPerInch: Integer; safecall;
+ function Get_PopupMode: TxPopupMode; safecall;
+ function Get_PrintScale: TxPrintScale; safecall;
+ function Get_Scaled: WordBool; safecall;
+ function Get_ScreenSnap: WordBool; safecall;
+ function Get_SnapBuffer: Integer; safecall;
+ function Get_UseDockManager: WordBool; safecall;
+ function Get_Visible: WordBool; safecall;
+ function Get_VisibleDockClientCount: Integer; safecall;
+ procedure _Set_Font(var Value: IFontDisp); safecall;
+ procedure Set_AlignWithMargins(Value: WordBool); safecall;
+ procedure Set_AutoScroll(Value: WordBool); safecall;
+ procedure Set_AutoSize(Value: WordBool); safecall;
+ procedure Set_AxBorderStyle(Value: TxActiveFormBorderStyle); safecall;
+ procedure Set_Caption(const Value: WideString); safecall;
+ procedure Set_Color(Value: OLE_COLOR); safecall;
+ procedure Set_DockSite(Value: WordBool); safecall;
+ procedure Set_DoubleBuffered(Value: WordBool); safecall;
+ procedure Set_DropTarget(Value: WordBool); safecall;
+ procedure Set_Enabled(Value: WordBool); safecall;
+ procedure Set_Font(const Value: IFontDisp); safecall;
+ procedure Set_HelpFile(const Value: WideString); safecall;
+ procedure Set_KeyPreview(Value: WordBool); safecall;
+ procedure Set_ParentCustomHint(Value: WordBool); safecall;
+ procedure Set_ParentDoubleBuffered(Value: WordBool); safecall;
+ procedure Set_PixelsPerInch(Value: Integer); safecall;
+ procedure Set_PopupMode(Value: TxPopupMode); safecall;
+ procedure Set_PrintScale(Value: TxPrintScale); safecall;
+ procedure Set_Scaled(Value: WordBool); safecall;
+ procedure Set_ScreenSnap(Value: WordBool); safecall;
+ procedure Set_SnapBuffer(Value: Integer); safecall;
+ procedure Set_UseDockManager(Value: WordBool); safecall;
+ procedure Set_Visible(Value: WordBool); safecall;
+ procedure Set_caseid(const Value: WideString); safecall;
+ procedure Set_data(const Value: WideString); safecall;
+ procedure Set_mode(const Value: WideString); safecall;
+ procedure Set_rewrite(const Value: WideString); safecall;
+ procedure Set_url(const Value: WideString); safecall;
+ procedure Set_userid(const Value: WideString); safecall;
+ procedure Set_username(const Value: WideString); safecall;
+ procedure Set_verify(const Value: WideString); safecall;
+ procedure Set_language(const Value: WideString); safecall;
+ procedure Set_modename(const Value: WideString); safecall;
+ procedure Set_userunit(const Value: WideString); safecall;
+ procedure Set_work_no(const Value: WideString); safecall;
+ procedure Set_loandoc_enable(const Value: WideString); safecall;
+ procedure Set_loandoc_value(const Value: WideString); safecall;
+ procedure Set_useproxy(const Value: WideString); safecall;
+ procedure Set_c_docnamelist(const Value: WideString); safecall;
+ procedure Set_c_docnolist(const Value: WideString); safecall;
+ procedure Set_fixfilelist(const Value: WideString); safecall;
+ procedure Set_is_in_wh(const Value: WideString); safecall;
+ procedure Set_oldcaseinfo(const Value: WideString); safecall;
+ function Get_c_docnamelist: WideString; safecall;
+ function Get_c_docnolist: WideString; safecall;
+ function Get_caseid: WideString; safecall;
+ function Get_data: WideString; safecall;
+ function Get_fixfilelist: WideString; safecall;
+ function Get_is_in_wh: WideString; safecall;
+ function Get_language: WideString; safecall;
+ function Get_loandoc_enable: WideString; safecall;
+ function Get_loandoc_value: WideString; safecall;
+ function Get_mode: WideString; safecall;
+ function Get_modename: WideString; safecall;
+ function Get_oldcaseinfo: WideString; safecall;
+ function Get_rewrite: WideString; safecall;
+ function Get_url: WideString; safecall;
+ function Get_useproxy: WideString; safecall;
+ function Get_userid: WideString; safecall;
+ function Get_username: WideString; safecall;
+ function Get_userunit: WideString; safecall;
+ function Get_verify: WideString; safecall;
+ function Get_work_no: WideString; safecall;
+ function Get_printyn: WideString; safecall;
+ procedure Set_printyn(const Value: WideString); safecall;
+ function Get_is_oldcase: WideString; safecall;
+ procedure Set_is_oldcase(const Value: WideString); safecall;
+ function Get_custdocyn: WideString; safecall;
+ procedure Set_custdocyn(const Value: WideString); safecall;
+ function Get_casenolength: WideString; safecall;
+ function Get_filesizelimit: WideString; safecall;
+ function Get_imgdpi: WideString; safecall;
+ function Get_scancolor: WideString; safecall;
+ procedure Set_casenolength(const Value: WideString); safecall;
+ procedure Set_filesizelimit(const Value: WideString); safecall;
+ procedure Set_imgdpi(const Value: WideString); safecall;
+ procedure Set_scancolor(const Value: WideString); safecall;
+ function Get_imgdelete: WideString; safecall;
+ procedure Set_imgdelete(const Value: WideString); safecall;
+ function Get_check_main_form: WideString; safecall;
+ function Get_isExternal: WideString; safecall;
+ procedure Set_check_main_form(const Value: WideString); safecall;
+ procedure Set_isExternal(const Value: WideString); safecall;
+ function Get_WH_CATEGORY: WideString; safecall;
+ procedure Set_WH_CATEGORY(const Value: WideString); safecall;
+ public
+ { Public declarations }
+ procedure Initialize; override;
+ end;
+
+implementation
+
+uses EnBarcode,
+ EnTransf, { for TImageTransform }
+ Enpnggr, { for PNGGraphic }
+ EnJpgGr, { for JPGGraphic }
+ EnReg,
+ EnBmpGr, { for TBitmapGraphic }
+ EnPrint, { for TEnvisionPrintMode, TDibGraphicPrinter }
+ ComObj, ComServ,IISUnit,IIS_File2Web,IIS_ImageProcess,
+ PatchFom,Doclist,ScanMemo,DocCopy,InputMask,SortMemo,DocPrt,OldCaseInfo;
+
+{$R *.DFM}
+
+{ TCB_IMGPSScanX }
+
+{$I CB_IMGPSScanImp_UI.pas}{$I CB_IMGPSScanImp_Scan.pas}{$I CB_IMGPSScanImp_Data.pas}{$I CB_IMGPSScanImp_Utils.pas}initialization
+ TActiveFormFactory.Create(
+ ComServer,
+ TActiveFormControl,
+ TCB_IMGPSScanX,
+ Class_CB_IMGPSScanX,
+ 1,
+ '',
+ OLEMISC_SIMPLEFRAME or OLEMISC_ACTSLIKELABEL,
+ tmApartment);
+
+ {SetLicenseKey('5B4451E676A1D2976FBB0F3BB18341336AF114C80B5ABAE7F6926B1CAF671F44' +
+ 'BD2F098CCEDA922F6389BFAE398DA6AEE67F97EEA0C17234C20D75C12173DBDA' +
+ '594924D56DD8E342F454389C836AD880BB4352CA3BE62C4933B1BA3828E7462C' +
+ '60514F2ECDAD322E6128D841F12D24DA00B623106D3F08EBCAA917D8A97CAA34' +
+ '3D65F2DA567316457395BF9123EE53DF235D181F191A5712DBB27735284AA92D' +
+ '5DFA0C8308308505F384707E900C6063F53F1BFF4C6972607955D1AE517B19D0' +
+ '82CDD16301885403AD229D57BAEF98C056F31430861E5F68F339D658D72E1F92' +
+ '63899412EC2D07891FE3AFD35F3E4A4390B2F0A8A1BF1B7D6160E5F1CC009B17'); }
+ SetLicenseKey('4B2CF65E8C2A86CE8A0DD0F6A7DB03BC0B0126168B48AE4C27EBD78CAE75CF0F' +
+ 'A612190861E0D99F6FAE3ED97AC1941B5E97843CFFCF705A3787989072D4EB2C' +
+ 'AE6CAB3F5B69B86616ACC8A37AD6A2AB21C7BDD5C9AE1EDF9E4193D353805C9A' +
+ '403631CE8A3D0803FEBB1BE4C209CE7A63B1298EF080EB34B8628CED567D2B68' +
+ 'E777FAC58E2E32B7411FC217A04336231D1E861A93474759DAA6EDF53F6EB632' +
+ 'A3055229A52F3053FB844754741409022DDE3DFB19473510F2BE63328E74BE20' +
+ 'A6A29AA24878F91ADA9DF8CE1F320AF4DAF58EBF95D9BE761D70EEA274E19475' +
+ '1C15948B184264C5C49E60493F3BCD2FFAE2CA8B021D00B96F45550C5F050D8A');
+
+
+ SetLicenseKey('A6A94A8D91B08A9D58F300C0573EA9EF1B9DB0BF69B90E13B958DB4CB6B44F5A' +
+ '4EE9CB22C9A68C2D07ED52ED4D13C755D890E4074996755361E6CDE2A6F1B563' +
+ '5DDC8999AC4D71FB092EA9F1F87BFA25694FBF0D6D250087D2B39629713FCCB0' +
+ 'D0A83135BC14FC63A4E8331CFF9E24C45C2D9CFD837EB70BAFDB79A75B7B97D5' +
+ 'E9EB271685118C29D90A7C85E7793908989E295DA50021C795A448366026E975' +
+ 'F49EA75B721B80427B99E5CF24A225FB498C07946ED7B806B483654C00D85C66' +
+ 'E34215CA3EDEF1D4C3F5896090E97E1E2C9752BA2D5B49EE58CF19A0D374077F' +
+ '6D13B90B6FED22D9EBC3AD6CDC76E595E08725BF2E12B8EF30A524A2E00504DF');
+end.
diff --git a/separate/scanImp/CB_IMGPSScanImp_Main.ts b/separate/scanImp/CB_IMGPSScanImp_Main.ts
new file mode 100644
index 0000000..a307ad0
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Main.ts
@@ -0,0 +1,17 @@
+import { applyDataMixins } from './CB_IMGPSScanImp_Data';
+import { applyScanMixins } from './CB_IMGPSScanImp_Scan';
+import { applyUIMixins } from './CB_IMGPSScanImp_UI';
+import { applyUtilsMixins, TStringList, TImageFormat, TTransMode, TFtpProtocol } from './CB_IMGPSScanImp_Utils';
+
+export class TCB_IMGPSScanX {
+ Ch_WriteNote=false; RejectCase=false; ErrIndex=0; Def_DeviceDelete=true; Def_DeviceDeleteSize=3072; Def_ScannerReverse=false; Def_BoardClear=false; Def_ScanDpi=300; Def_ScanDuplex=true; Def_ScanRotate=0; Def_ScanDeskew=false; Def_ScanBright=0; Def_ScanContrast=0; Def_ScanImgShowMode=2; Def_ScanImgSetUse=false;
+ FUrl=''; FCaseID=''; FMode=''; FModeName=''; FWork_no=''; FUserID=''; FUserName=''; FUserUnit=''; FData=''; FVerify=''; FReWrite=''; FLanguage='zh_tw'; FLoanDoc_Value=''; FLoanDoc_Enable=''; FUseProxy=''; FC_DocNoList=''; FC_DocNameList=''; FFixFileList=''; FIs_In_Wh=''; FOldCaseInfo=''; FPrintyn=''; FIs_OldCase=''; FCustDocYN=''; FImgDPI=300; FScanColor=0; FFileSizeLimit=5120; FCaseNoLength=16; FImgDelete='N'; FIsExternal='N'; FCheck_main_form='N'; FWH_category='N';
+ TransMode=TTransMode.tsNone; HttpErrStr=''; FFtpIP=''; FFtpID=''; FFtpPwd=''; FFtpRootPath=''; FFtpExtraPath=''; FFtpPort=0; FFtpProtocol=TFtpProtocol.fpftp; DeviceDelete=false; DeviceDeleteSize=0; ScannerReverse=false; BoardClear=false; ScanDpi=0; ScanDuplex=false; ScanRotate=0; ScanDeskew=false; ScanBright=0; ScanContrast=0; ScanImgShowMode=0; ScanImgSetUse=false; ScanColor:TImageFormat='ifBlackWhite';
+ ServerDate=''; ServerTime=''; Balance=0; ScanDenialTime=''; ScanDenialHint=''; ScanPath=''; ImagePath=''; ImageSavePath=''; ScaniniPath=''; LngPath=''; CheckXmlPath=''; SitePath=''; SamplePath=''; TransPath=''; ScanSaveFilename=''; ScanCaseno=''; ScanDocDir='';
+ Doc_Inf_List=new TStringList(); DM_FORM_INF_List=new TStringList(); FORM_INF_List=new TStringList(); CHECK_RULE_INF_List=new TStringList(); MEMO_INF_List=new TStringList(); WORK_INF_List=new TStringList(); LASTEST_FORM_INF_List=new TStringList(); FindResult=new TStringList(); CaseList=new TStringList(); Context_DocnoList=new TStringList(); CaseDocNoList=new TStringList(); CaseDocNo_CopiesList=new TStringList(); ContextList=new TStringList(); AttContextList=new TStringList(); OMRFileList=new TStringList(); Cust_DocNoList=new TStringList(); IN_WH_DocNoList=new TStringList(); FormCode_PageSize=new TStringList(); DocNo_NeedDoc=new TStringList(); DocNo_NoDoc=new TStringList(); DocNo_VerinCase=new TStringList(); NoSaveBarCodeList=new TStringList(); FormID_List=new TStringList(); DocNo_List=new TStringList(); NowShowFileList=new TStringList(); NowSelectFileList=new TStringList(); GuideFormIDList=new TStringList(); DivPageFormIDList=new TStringList(); LastInitFormidList=new TStringList(); LastAddFormidList=new TStringList(); SampleFormIDList=new TStringList(); ExistImgList=new TStringList(); reSizeExistImgList=new TStringList();
+ NowCaseno=''; NowDocNo=''; NowDocDir=''; NowFormCode=''; NowFormName=''; NowPage=0; DisplayPath=''; Case_loandoc=''; UpLPoint={X:0,Y:0}; UpRPoint={X:0,Y:0}; DownLPoint={X:0,Y:0}; DownRPoint={X:0,Y:0}; Point_Width=''; Point_Height=''; CaseIDLength=0; FormIDLength=0; DocNoLength=0; PEFileName=''; DownFileErrStr='';
+ ISB:any=null; ScanInfo:any={}; TwainShowUI=false; MpsBarcodeinf:any={}; ScanMode:any=null; Mpskey=''; Seg=0; VMode=0; NowClick=0; ScanIP=''; DisplayISB:any=null; SelectISB:any=null; SelectPage=0; NewTreeNode:any=null; MyTreeNode1:any=null; MyTreeNode2:any=null; MyTreeNode3:any=null; InitialOk=false; ShowText=''; Ext=''; SafePixel=0; OMRErrInfo:any[]=[]; ScrollRec:any[]=[]; RecHozPos=0; RecVerPos=0; ReczoomPercent=0; SortMode=false; PreMytreeNode2Name=''; HS=0; VS=0; iRate=0; Bt=0; BarCodeRotate=0; HaveAppDoc=false; PageLVclear=false; CaseCount=0; PageCount=0; Item:any=null; SampleAnchorMode=''; DownImgStatus=''; TransForm_Field=''; NowWork_No=''; CropBarcode=''; Has_Authorize=''; AttName=''; NowGuideFormID=''; NowDivPageFormID=''; FirstDocDir=''; FMaxUploadSize=''; FJpgCompression=0; Draging=false; MDown=false; FEvents:any=null;
+ [key: string]: any;
+ constructor(){ console.log("TCB_IMGPSScanX Initialized"); }
+}
+applyDataMixins(TCB_IMGPSScanX); applyScanMixins(TCB_IMGPSScanX); applyUIMixins(TCB_IMGPSScanX); applyUtilsMixins(TCB_IMGPSScanX);
diff --git a/separate/scanImp/CB_IMGPSScanImp_Scan.pas b/separate/scanImp/CB_IMGPSScanImp_Scan.pas
new file mode 100644
index 0000000..b304dba
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Scan.pas
@@ -0,0 +1,1050 @@
+function TCB_IMGPSScanX.Get_Color: OLE_COLOR;
+begin
+ Result := OLE_COLOR(Color);
+end;
+
+procedure TCB_IMGPSScanX.Set_Color(Value: OLE_COLOR);
+begin
+ Color := TColor(Value);
+end;
+
+procedure TCB_IMGPSScanX.StatrTwainScan;
+var ScanInfo : TScanInfo;
+ i : Integer;
+begin
+ if not Scanner.IsConfigured then
+ begin
+ ShowMessage(_Msg('TWAIN 掃瞄驅動尚未安裝'));
+ Exit;
+ end;
+ FillChar(ScanInfo, SizeOf(ScanInfo), 0);
+ ScanInfo.MultiPage := True;
+ ScanInfo.ImageCount := 0;
+ ScanInfo.Graphic := TTiffGraphic.Create;
+ try
+ ISB := nil; //規零
+//ShowMessage(IntToStr(ScanDpi));
+ Scanner.RequestedXDpi := ScanDpi;
+ Scanner.RequestedYDpi := ScanDpi;
+ Scanner.RequestedImageFormat := ScanColor;
+ Scanner.ShowUI := TwainShowUI;
+
+ Try
+ Scanner.OpenSource;
+ Scanner.Duplex := ScanDuplex; //雙面
+
+ if FMode='SAMPLESCAN' then
+ Scanner.Duplex:=False;
+
+ //Scanner.FEEDERENABLED := not ScanFlatCB.Checked; // 先拿掉平台
+ If ScanImgSetUse Then
+ begin
+ Scanner.ScanBrightness := ScanBright;
+ Scanner.ScanContrast := ScanContrast;
+ end;
+ except
+ Showmessage(_Msg('掃瞄器發生錯誤!!'));
+ Scanner.CloseSource;
+ Exit;
+ end;
+ try
+ Try
+ Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));
+ Except
+ Scanner.CloseSource;
+ end;
+ finally
+ Scanner.CloseSource;
+ end;
+ finally
+ Scanner.CloseSource;
+ ScanInfo.Graphic.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.OnAcquire( const DibHandle : THandle;
+ const XDpi : Word;
+ const YDpi : Word;
+ const CallBackData : LongInt );
+var
+ pScanInfo : TpScanInfo;
+ SaveFileName : String;
+ SaveStream : TFileStream;
+ strResults : TBarcodeStringResult;
+ DeleteStm : TMemoryStream;
+ isDelete : Boolean;
+ iGraphic,iGraphic_First,iGraphic_sec : TTiffGraphic;
+ iRect : TRect;
+ JpgGr : TJpegGraphic;
+ i : Integer;
+ TagTxt : String;
+ function Deletepage(Graphic:TDibGraphic;BlankSize:Integer):Boolean;
+ begin
+ DeleteStm := TMemoryStream.Create;
+ DeleteStm.Seek(0,soFromBeginning);
+ Graphic.AppendToStream(DeleteStm);
+
+ //DeleteStm.LoadFromFile(Path+'temp.tif');
+ //Isb1.Graphic.SaveToStream(DeleteStm);
+ //Isb1.Graphic.AppendToStream(DeleteStm);
+ if DeleteStm.Size < BlankSize Then
+ Result:= True
+ Else
+ Result := False;
+
+ DeleteStm.Free;
+ //DeleteFile(Path+'temp.tif');
+ end;
+begin
+ pScanInfo := TpScanInfo(CallBackData);
+ isDelete := False;
+
+ if pScanInfo^.MultiPage then
+ begin
+ pScanInfo^.Graphic.AssignFromDibHandle(DibHandle);
+ pScanInfo^.Graphic.XDotsPerInch := XDpi;
+ pScanInfo^.Graphic.YDotsPerInch := YDpi;
+ TagTxt := 'height:'+inttostr(pScanInfo^.Graphic.Height)+',width:'+inttostr(pScanInfo^.Graphic.Width);
+ if pScanInfo^.Graphic.ImageFormat = ifBlackWhite then
+ begin
+ ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
+ ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
+
+ pScanInfo^.Graphic.Compression := tcGroup4;
+ MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf);
+ For i := 1 to MpsBarcodeinf.count do
+ begin
+ If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
+ begin
+ Rotate(pScanInfo^.Graphic,MpsBarcodeinf.r180[i]);
+ MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf); //旋轉後再重取一次條碼資訊
+ Break;
+ end;
+ end;
+
+ //影像反向
+ IF ScannerReverse then
+ NegativeImg(pScanInfo^.Graphic);
+ //傾斜矯正
+ IF ScanDeskew Then
+ DeskewImg(pScanInfo^.Graphic);
+ //清黑邊
+ IF BoardClear then
+ CleanupBorder(pScanInfo^.Graphic);
+ end
+ else if pScanInfo^.Graphic.ImageFormat = ifTrueColor then
+ begin
+ //Ext := '.jpg';
+ ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
+ //ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
+ MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
+ For i := 1 to MpsBarcodeinf.count do
+ begin
+ If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
+ begin
+ Rotate(ISB_BW.Graphic,MpsBarcodeinf.r180[i]);
+ MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf); //旋轉後再重取一次條碼資訊
+ Break;
+ end;
+ end;
+ pScanInfo^.Graphic.Compression := tcJpeg;
+ pScanInfo^.Graphic.JpegQuality := FJpgCompression;
+ end
+ else if pScanInfo^.Graphic.ImageFormat = ifColor256 Then
+ begin
+ //Ext := '.jpg';
+ ConvertToGray(pScanInfo^.Graphic);
+ pScanInfo^.Graphic.Compression := tcJpeg;
+ pScanInfo^.Graphic.JpegQuality := FJpgCompression;
+ end
+ else if pScanInfo^.Graphic.ImageFormat = ifGray256 Then
+ begin
+ //Ext := '.jpg';
+ ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
+ ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
+ MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
+ For i := 1 to MpsBarcodeinf.count do
+ begin
+ If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
+ begin
+ Rotate(ISB_BW.Graphic,MpsBarcodeinf.r180[i]);
+ MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf); //旋轉後再重取一次條碼資訊
+ Break;
+ end;
+ end;
+ pScanInfo^.Graphic.Compression := tcJpeg;
+ pScanInfo^.Graphic.JpegQuality := FJpgCompression;
+//ShowMessage(IntToStr(pScanInfo^.Graphic.JpegQuality));
+//if pScanInfo^.Graphic.Compression = tcJpeg then
+//begin
+//ShowMessage('jpg');
+//end;
+
+ end
+ else
+ begin
+ //Ext := '.tif';
+ pScanInfo^.Graphic.Compression := tcPackBits;
+ end;
+
+ end;
+ //Application.ProcessMessages;
+ iGraphic_First := TTiffGraphic.Create;
+ iGraphic_sec := TTiffGraphic.Create;
+ //iGraphic := TTiffGraphic.Create;
+ try
+ iGraphic_First.Assign(pScanInfo^.Graphic);
+ //Application.ProcessMessages;
+ if CheckNeedCrop(iGraphic_First) Then
+ begin
+ iRect.Left := pScanInfo^.Graphic.Width div 2; //先取左邊的影像
+ iRect.Top := 0;
+ iRect.Right := pScanInfo^.Graphic.Width;
+ iRect.Bottom := pScanInfo^.Graphic.Height;
+ CropImg(iGraphic_First,iRect);
+
+ iGraphic_Sec.Assign(pScanInfo^.Graphic); //再取右邊的影像
+ iRect.Left := 0;
+ iRect.Top := 0;
+ iRect.Right := pScanInfo^.Graphic.Width div 2;
+ iRect.Bottom := pScanInfo^.Graphic.Height;
+ CropImg(iGraphic_Sec,iRect);
+ end;
+ //iGraphic.Assign(iGraphic_First);
+ iGraphic := iGraphic_First;
+
+ if iGraphic.ImageFormat=ifGray256 then //20180104
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=FJpgCompression;
+ end;
+ if iGraphic.ImageFormat=ifTrueColor then //20180104
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=FJpgCompression;
+ end;
+
+//ShowMessage('WTF');
+ while not iGraphic.IsEmpty do
+ begin
+ //Application.ProcessMessages;
+ IF (not DeviceDelete) or (not Deletepage(iGraphic,DeviceDeleteSize)) Then
+ begin
+ ImageScrollBox1.Graphic.Assign(iGraphic);
+ ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
+
+ MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
+ For i := 1 To MpsBarcodeinf.Count Do
+ Begin
+ If MpsBarcodeinf.r180[i] <> 0 Then // 依條碼角度轉影像
+ Begin
+ Rotate(iGraphic, MpsBarcodeinf.r180[i]);
+ Break;
+ End;
+ End;
+
+ if iGraphic.ImageFormat=ifGray256 then //20180104 因此旋轉後變為回packbits 所以要改為jpeg
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=FJpgCompression;
+ end;
+ if iGraphic.ImageFormat=ifTrueColor then
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=FJpgCompression;
+ end;
+ PageEnd;
+ IF PEFileName <> '' Then
+ begin
+ IF LowerCase(ExtractFileExt(PEFileName)) = '.tif' Then
+ begin
+ if FileExists( PEFileName ) then
+ SaveStream := TFileStream.Create( PEFileName ,fmOpenReadWrite)
+ Else
+ SaveStream := TFileStream.Create( PEFileName ,fmCreate );
+ try
+ SaveStream.Seek(0, soFromBeginning);
+ iGraphic.AppendToStream(SaveStream);
+ finally
+ SaveStream.Free;
+ end;
+ end
+ Else IF LowerCase(ExtractFileExt(PEFileName)) = '.jpg' Then
+ begin
+ if FileExists( PEFileName ) then
+ DeleteFile(PEFileName);
+ //SaveStream := TFileStream.Create( PEFileName ,fmCreate );
+ JpgGr := TJpegGraphic.Create;
+ try
+ JpgGr.Assign(iGraphic);
+ JpgGr.SaveQuality := FJpgCompression;
+ //JpgGr.AppendToStream(SaveStream);
+ JpgGr.SaveToFile(PEFileName);
+ finally
+ JpgGr.Free;
+ //SaveStream.Free;
+ end;
+ end;
+ PageDone;
+ end;
+ end;
+ if iGraphic = iGraphic_First then
+ iGraphic := iGraphic_Sec
+ else
+ iGraphic.Assign(nil);
+ //iGraphic.Assign(iGraphic_Sec);
+ end;
+ finally
+ //iGraphic.Free;
+ iGraphic_First.Free;
+ iGraphic_Sec.Free;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.R_W_Scanini(Mode:Char); //'R'讀取;'W'寫入
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(ScaniniPath+'FBScan.ini');
+ try
+ case Mode of
+ 'R':begin
+ DeviceDelete := ini.ReadBool('DeviceDelete','Mode',Def_DeviceDelete);
+ DeviceDeleteSize := ini.ReadInteger('DeviceDelete','Size_New',Def_DeviceDeleteSize);
+ ScannerReverse := ini.ReadBool('Scanner','Reverse',Def_ScannerReverse);
+ BoardClear := ini.ReadBool('Scanner','BoardClear',Def_BoardClear);
+ //ScanDpi := ini.ReadInteger('Scanner','Dpi',Def_ScanDpi);
+ //ScanDuplex := ini.ReadBool('Scanner','Duplex',Def_ScanDuplex);
+ ScanRotate := ini.ReadInteger('Scanner','ScanRotate',Def_ScanRotate);
+ ScanDeskew := ini.ReadBool('Scanner','ScanDeskew',Def_ScanDeskew);
+ ScanBright := ini.ReadInteger('Scanner','ScanBright',Def_ScanBright);
+ ScanContrast := ini.ReadInteger('Scanner','ScanContrast',Def_ScanContrast);
+ ScanImgShowMode := ini.ReadInteger('Scanner','ScanImgShowMode',Def_ScanImgShowMode);
+ ScanImgSetUse := ini.ReadBool('Scanner','ScanImgSetUse',Def_ScanImgSetUse); //20101110 BA說掃瞄器廠商有調設定要新增此選項是否啟動
+ end;
+ 'W':begin
+ ini.WriteBool('DeviceDelete','Mode',DeviceDelete);
+ ini.WriteInteger('DeviceDelete','Size_New',DeviceDeleteSize);
+ ini.WriteBool('Scanner','Reverse',ScannerReverse);
+ ini.WriteBool('Scanner','BoardClear',BoardClear);
+ //ini.ReadInteger('Scanner','Dpi',ScanDpi);
+ //ini.WriteBool('Scanner','Duplex',ScanDuplex);
+ ini.WriteInteger('Scanner','ScanRotate',ScanRotate);
+ ini.WriteBool('Scanner','ScanDeskew',ScanDeskew);
+ ini.WriteInteger('Scanner','ScanBright',ScanBright);
+ ini.WriteInteger('Scanner','ScanContrast',ScanContrast);
+ ini.WriteInteger('Scanner','ScanImgShowMode',ScanImgShowMode);
+ ini.WriteBool('Scanner','ScanImgSetUse',ScanImgSetUse); //20101110 BA說掃瞄器廠商有調設定要新增此選項是否啟動
+ end;
+ end;
+
+ finally
+ ini.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.GetDefScanIni; //取得掃瞄的預設值
+var
+ i : Integer;
+ PARA_NO,PARA_CONTENT: String;
+begin
+ Def_DeviceDelete := True;
+ Def_DeviceDeleteSize := 3072; //20120821 改成3000(出現)
+ Def_ScannerReverse := False;
+ Def_BoardClear := False;
+ Def_ScanDpi := 300;
+ Def_ScanDuplex := True;
+ Def_ScanRotate := 0;
+ Def_ScanDeskew := False;
+ Def_ScanImgSetUse := False;
+ Def_ScanBright := 0;
+ Def_ScanContrast := 0;
+ Def_ScanImgShowMode := 2;
+
+ for i := 0 to WORK_INF_List.Count - 1 do
+ begin
+ IF GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BLANKDEL_USE' Then //空白頁啟動
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_DeviceDelete := True
+ Else
+ Def_DeviceDelete := False;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BLANKDEL_SIZE' Then //空白頁Size
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT = '' then
+ Def_DeviceDeleteSize := 0
+ Else
+ Def_DeviceDeleteSize := Strtoint(PARA_CONTENT);
+
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_REVERSE' Then //是否需反相
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_ScannerReverse := True
+ Else
+ Def_ScannerReverse := False;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BOARDCLEAR' Then //是否清黑邊
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_BoardClear := True
+ Else
+ Def_BoardClear := False;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DPI' Then //掃瞄DPI
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT = '' then
+ Def_ScanDpi := 300
+ else
+ Def_ScanDpi := Strtoint(PARA_CONTENT);
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DUPLEX' Then //是否雙面掃瞄
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_ScanDuplex := True
+ Else
+ Def_ScanDuplex := False;
+
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_ROTATE_MODE' Then //掃瞄時旋轉角度
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT = '0' then
+ Def_ScanRotate := 0
+ Else if PARA_CONTENT = '1' then
+ Def_ScanRotate := 270
+ Else if PARA_CONTENT = '2' then
+ Def_ScanRotate := 180
+ Else if PARA_CONTENT = '3' then
+ Def_ScanRotate := 90
+ Else
+ Def_ScanRotate := 0;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DESKEW' Then //是否傾斜矯正
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_ScanDeskew := True
+ Else
+ Def_ScanDeskew := False;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_IMGSET_USE' Then //是否使用亮度對比設定
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if UpperCase(PARA_CONTENT) ='Y' then
+ Def_ScanImgSetUse := True
+ else
+ Def_ScanImgSetUse := False;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BRIGHT' Then //亮度
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT ='' then
+ Def_ScanBright := 0
+ Else
+ Def_ScanBright := strtoint(PARA_CONTENT);
+ if (Def_ScanBright > 255) or (Def_ScanBright < -255) then
+ Def_ScanBright := 0;
+
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_CONTRAST' Then //對比
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT ='' then
+ Def_ScanContrast := 0
+ Else
+ Def_ScanContrast := strtoint(PARA_CONTENT);
+ if (Def_ScanContrast > 255) or (Def_ScanContrast < -255) then
+ Def_ScanContrast := 0;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_SHOW_MODE' Then
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ if PARA_CONTENT = '0' then
+ Def_ScanImgShowMode := 0
+ Else if PARA_CONTENT = '1' then
+ Def_ScanImgShowMode := 1
+ Else if PARA_CONTENT = '2' then
+ Def_ScanImgShowMode := 2
+ Else
+ Def_ScanImgShowMode := 0;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'CASE_IN_TIME' Then //取進件截止時間
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ ScanDenialTime := PARA_CONTENT;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_HINT' Then //掃描提示字串
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ ScanDenialHint := PARA_CONTENT;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'NO_SAVE_FORM_ID' Then //掃描不存檔之表單代號
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ NoSaveBarCodeList.CommaText := PARA_CONTENT;
+ end
+ Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'LOCAL_PATH' Then //本機端路徑
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ ImagePath:= PARA_CONTENT;
+ end
+ Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'GUIDEFORMID' Then //當導引頁的表單
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ GuideFormIDList.CommaText := PARA_CONTENT;
+ end
+ Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'DIVPAGEFORMID' Then //當分案頁的表單
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ DivPageFormIDList.CommaText := PARA_CONTENT;
+ end
+ Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'FILE_COMPRESSION' Then //20171211 jpg to tif 壓縮比
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ FJpgCompression := StrToInt(PARA_CONTENT);
+ end
+ Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'MAX_UPLOAD_SIZE' Then //取得 上傳大小的限制(MB)
+ begin
+ PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
+ FMaxUploadSize := PARA_CONTENT;
+ end;
+ end;
+ ScanDuplex := Def_ScanDuplex;
+end;
+
+procedure TCB_IMGPSScanX.EnableImage(v:integer;Sender : TObject);
+var bmp : Tbitmap;
+begin
+ DesableImage;
+ bmp := TBitmap.Create;
+ try
+ ImageList3.GetBitmap(v,bmp);
+ TBitBtn(Sender).Glyph.Assign(bmp);
+ finally
+ bmp.Free;
+ end;
+ ViewMouseMode(v);
+end;
+
+procedure TCB_IMGPSScanX.DesableImage;
+var bmp : Tbitmap;
+ i : integer;
+begin
+ NowClick := -1;
+ bmp := Tbitmap.Create;
+ try
+ For i:= 0 to 6 do
+ begin
+ ImageList4.GetBitmap(i,bmp);
+ TBitBtn(FindComponent('FC'+IntToStr(i))).Glyph.Assign(bmp);
+ bmp.Width:=0;
+ bmp.Handle:=0;
+ end;
+ finally
+ bmp.Free;
+ end;
+ ViewMouseMode(NowClick);
+end;
+
+Procedure TCB_IMGPSScanX.DeleteImageFile(Path,FileName,CaseID:String); // 刪除檔案 (無法得到DocDir用)
+var
+ i : Integer;
+ FileList:TStringlist;
+ DocDir : String;
+begin
+
+
+ DeleteFile(Path+FileName);
+ DocDir := Path2DocDir(Path,CaseID);
+//ShowMessage('DocDir='+DocDir);
+ SetContextList('D',-1,CaseID,DocDir,FileName);
+ {FileList:=TStringlist.Create;
+ try
+ if FileExists(Path+'Context.dat') then
+ FileList.LoadFromFile(Path+'Context.dat');
+ for i := 0 to FileList.Count - 1 do
+ begin
+ if FileName = FileList.Strings[i] then
+ begin
+ FileList.Delete(i);
+ FileList.SaveToFile(Path+'Context.dat');
+ Break;
+ end;
+ end;
+ if FileList.Count = 0 then
+ DeleteFile(Path+'Context.dat');
+ finally
+ FileList.Free;
+ end;}
+end;
+
+Function TCB_IMGPSScanX.DeleteDocNoFileForESCAN(Path,DocNo:String):Boolean; //刪除指定DocNo文件
+var
+ i,j,k: Integer;
+ FName : String;
+ ST1,ST2,ST3:TStringList;
+
+begin
+
+ Result := False;
+//ShowMessage(DocNo);
+ for i := ContextList.Count - 1 downto 0 do
+ begin
+ FName := ContextList.Strings[i];
+ If (DocNo = FormCode2DocNo(FileName2FormCode(FName))) or (DocNo=AttName) then
+ begin
+ if not ISExistImg(Path+'\'+FName) then
+ begin
+ DeleteFile(Path+'\'+FName);
+ ContextList.Delete(i);
+ end;
+ Result := True; //有刪到指定文件
+ end;
+ end;
+ ContextList.SaveToFile(Path+'\Context.dat');
+ ContextList.LoadFromFile(Path+'\Context.dat');
+
+ if ContextList.Count=0 then
+ begin
+ _DelTree(Path);
+ SetDocNoList('D',-1,NowCaseNo,NowDocDir,'');
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.DownLoadImage(Path,CaseID:String):Boolean;
+begin
+ Result := True;
+ if not GetftpInfo(CaseID,'download') then //取案件下載方式
+ begin
+ DownFileErrStr := _Msg('取案件下載資訊失敗,')+HttpErrStr;
+ Result := False;
+ Exit;
+ end;
+ case TransMode of
+ tsHttp:
+ begin
+ ShowText := _Msg('案件下載中(Http),請稍候');
+ DataLoading(True,True);
+ If not Down_Img(ImageSavePath+FCaseID+'\Download\',FCaseID) then
+ begin
+ Showmessage(FCaseID+_msg('載入異動影像時,網路發生錯誤')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+ end;
+ tsFtp:
+ begin
+ ShowText := _Msg('案件下載中(Ftp),請稍候');
+ DataLoading(True,True);
+ SetFtpInfo;
+
+ if not IIS_Ftp.FtpsConnect then
+ begin
+ DownFileErrStr := Format(_Msg('無法連上Ftp主機,錯誤原因:%s')+#13+'%s',[FtpErrReason,FTPSClient1.LastReceivedReply]);
+ Result := False;
+ Exit;
+ end;
+ if not IIS_Ftp.FtpsDownloadFile(FFtpExtraPath,CaseID+'.zip',Path+CaseID+'.zip',display1) then
+ begin
+ DownFileErrStr := Format(_Msg('錯誤原因:%s'),[FtpErrStr]);
+ Result := False;
+ Exit;
+ end;
+ ExecuteUnZip(Path+CaseID+'.zip',Path,False);
+ DeleteFile(Path+CaseID+'.zip');
+ end;
+ end;
+end;
+
+
+Procedure TCB_IMGPSScanX.CaseResort2Scanlist(Path:String); //案件的檔案重新排序給scanlist(次文件依FormID排)
+var
+ i,n,v,v1 : Integer;
+ S,S1 : TStringlist;
+ FormID,OldName,NewName,DocNo,Doc_Type:String;
+ x : Integer;
+begin
+ S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ if FileExists(Path+'Context.dat') then
+ S.LoadFromFile(Path+'Context.dat');
+ X := 0;
+ for I := 1 to FORM_INF_List.Count - 1 do //在FormID有設定的 //主文件 照SQL排 20101028改
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ if FormCode2FileName(FormID,S) = '' then
+ Continue;
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FileName2FormCode(S.Strings[n]) = FormID) and (Doc_Type='1') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;
+
+ for I := 0 to FORM_INF_List.Count - 1 do //次文件 照SQL排 20110512為了某個文件要先打的原因要求改
+ begin
+
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ if FormCode2FileName(FormID,S) = '' then
+ Continue;
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FileName2FormCode(S.Strings[n]) = FormID) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;
+
+ {for I := 0 to Doc_Inf_List.Count - 1 do //次文件 照文件代碼+掃瞄順序排 20101101改 20110512晚上又說改回來
+ begin
+ DocNo := GetSQLData(Doc_Inf_List,'DOC_NO',i);
+ Doc_Type := GetSQLData(Doc_Inf_List,'DOC_TYPE',i);
+ for n := 0 to S.Count - 1 do
+ begin
+ if (S.Strings[n][1] <> '*') and (FormCode2DocNo(FileName2FormCode(S.Strings[n])) = DocNo) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;}
+
+ {for n := 0 to S.Count - 1 do //次文件 照掃瞄順序排 20101028改
+ begin
+ for i := 0 to FORM_INF_List.Count - 1 do
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ Doc_Type := GetSQLData(FORM_INF_List,'T2.DOC_TYPE',i);
+ if (S.Strings[n][1] <> '*') and (FileName2FormCode(S.Strings[n]) = FormID) and (Doc_Type='2') then
+ begin
+ Inc(X);
+ OldName := S.Strings[n];
+ NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3); //從原有數量加1開始編
+ S.Strings[n] := '*'+S.Strings[n];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+ end;}
+ for i := 0 to S.Count - 1 do //FormID沒設定的或附件
+ begin
+ if S.Strings[i][1] <> '*' then
+ begin
+ Inc(X);
+ OldName := S.Strings[i];
+ //NewName := Add_Zoo(S.Count+x,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(S.Count+x,3)+FileName2NoQuene_Filename(OldName);
+ S.Strings[i] := '*'+S.Strings[i];
+ S1.Add(OldName+','+NewName);
+ end;
+ end;
+
+ S.Clear;
+ for i := 0 to S1.Count - 1 do //開始轉換檔名
+ begin
+ v := Pos(',',S1.Strings[i]);
+ v1 := length(S1.Strings[i]);
+ OldName := copy(S1.Strings[i],1,v-1);
+ NewName := copy(S1.Strings[i],v+1,v1-v);
+ //if FileExists(Path+OldName) then
+ //begin
+ //ReNameFile(Path+OldName,Path+NewName);
+ S.Add(NewName);
+ S.SaveToFile(Path+'scanlist.dat');
+ //end;
+ end;
+ ReSortFileName2Scanlist(Path);
+ finally
+ S.Free;
+ S1.Free;
+ end;
+end;
+
+
+Procedure TCB_IMGPSScanX.GetSelectImageFile;
+var
+ i : Integer;
+ FormID,FormName,DocNo : String;
+ PreNode2Name : String;
+ iFormID : String;
+ iISBName : String;
+ iISB : TImageScrollBox;
+begin
+ NowSelectFileList.Clear;
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+ NowSelectFileList.Add(iISB.FileName);
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ParserPoint(S:String); //解析十字點的字串
+var
+ PointList : TStringlist;
+ Rect : TRect;
+begin
+ PointList := TStringlist.Create;
+ try
+ PointList.Text := S;
+ IF PointList.Count <> 6 Then
+ begin
+ UpLPoint := Str2Point('0,0');
+ UpRPoint := Str2Point('0,0');
+ DownLPoint := Str2Point('0,0');
+ DownRPoint := Str2Point('0,0');
+ Point_Width := '0';
+ Point_Height := '0';
+ end
+ Else
+ begin
+ UpLPoint := Str2Point(PointList[0]);
+ DownLPoint := Str2Point(PointList[1]);
+ UpRPoint := Str2Point(PointList[2]);
+ DownRPoint := Str2Point(PointList[3]);
+ Point_Width := PointList[4];
+ Point_Height := PointList[5];
+ end;
+ finally
+ PointList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckScanDenialTime:Boolean;
+Var
+ NowTime : String;
+begin
+ NowTime := GetBalance2Time(Balance);
+ NowTime := Copy(NowTime,1,2)+':'+Copy(NowTime,3,2)+':'+Copy(NowTime,5,2);
+ Result := True;
+ if ScanDenialTime <> '' then
+ begin
+ if StrtoTime(NowTime) >= StrtoTime(ScanDenialTime) then
+ Result := False;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.initkscan;
+begin
+ ScanDuplexCB.Enabled := False;
+ if Scanner.IsConfigured then
+ begin
+ try
+ Scanner.OpenSource;
+ IF Scanner.DuplexCap > 0 Then
+ begin
+ ScanDuplexCB.Enabled := True;
+ end;
+ {IF Scanner.FEEDERCAP Then
+ ScanFlatCB.Enabled := True; }
+ Except
+ DataLoading(False,True);
+ Exit;
+ end;
+ Scanner.CloseSource;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
+Var
+ i,FormIDCount : Integer;
+begin
+ Result := False;
+ FormIDCount := 0;
+ if (Graphic.Width > (4 * Graphic.XDotsPerInch)) {or (Graphic.Height > (15 * Graphic.YDotsPerInch))} then
+ //if (Graphic.Width > (6 * Graphic.XDotsPerInch)) then
+ begin
+ for I := 1 to MpsBarcodeinf.Count do
+ begin
+ if (Length(MpsBarcodeinf.Text[i])=FormIDLength) and FormIDExists(MpsBarcodeinf.Text[i],False,0) then
+ begin
+ inc(FormIDCount);
+ end;
+ end;
+
+ end;
+
+//ShowMessage('FormIDCount='+IntToStr(FormIDCount)+#10#13+'MpsBarcodeinf.count='+IntToStr(MpsBarcodeinf.count));
+ if FormIDCount = 2 then
+ begin
+ Result := True;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.MoveImage(Path:String;mp:Integer); //移動頁數
+var
+ i,n,inx:Integer;
+ FList,D_Flist:TStringlist;
+begin
+ FList := TStringlist.Create;
+ D_Flist := TStringlist.Create;
+ try
+ FList.LoadFromFile(Path+'Context.dat');
+ //Showmessage(Path);
+ //Showmessage(Flist.Text);
+ for i := 0 to FList.Count - 1 do
+ begin
+ Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);
+ Flist.Strings[i]:= '@'+Flist.Strings[i];
+ end;
+
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ inx := strtoint(Copy(TShape(Components[i]).Name,3,length(TShape(Components[i]).Name)-2));
+ D_Flist.Add(Flist.Strings[inx-1]);
+ //Renamefile(Path+Flist.Strings[inx-1],path+'@'+Flist.Strings[inx-1]);
+ end;
+ end;
+ //Showmessage('aa');
+ for i := 0 to D_Flist.Count -1 do
+ begin
+ for n := 0 to FList.Count - 1 do
+ begin
+ //if Flist.Strings[n]=StringReplace(D_Flist.Strings[i],'@','',[rfReplaceAll]) then
+ if Flist.Strings[n]=D_Flist.Strings[i] then
+ begin
+ Flist.Delete(n);
+ Break;
+ end;
+ end;
+ end;
+ //Showmessage('bb');
+ for i := 0 to D_Flist.Count - 1 do
+ begin
+ Flist.Insert(mp-1+i,D_Flist.Strings[i]);
+ end;
+
+ Flist.SaveToFile(Path+'Context.dat');
+ //Showmessage(Flist.Text);
+ //Showmessage('CC');
+ ReSortFileName(Path);
+ TreeView1click(self);
+
+
+ finally
+ FList.Free;
+ D_Flist.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FileName2ScanPage(FileName:String):Integer; //從檔名轉出掃瞄頁數
+Var
+ v : Integer;
+ FName : String;
+begin
+ FName := ExtractFileName(FileName);
+ v := Pos('_',FName);
+ if v = 0 then //附件
+ v := pos('.',FName);
+ Result := Strtoint(Copy(FName,1,v-1));
+end;
+
+Procedure TCB_IMGPSScanX.ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
+var
+ i : Integer;
+ OldName,NewName : String;
+ S : TStringlist;
+begin
+ S := TStringlist.Create;
+ try
+ if FileExists(Path+'scanlist.dat') then
+ S.LoadFromFile(Path+'scanlist.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+ OldName := S.Strings[i];
+ //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
+ //ReNameFile(Path+OldName,Path+NewName);
+ S.Strings[i] := NewName;
+ end;
+ S.SaveToFile(Path+'scanlist.dat');
+ finally
+ S.Free;
+ end;
+end;
+
+
+function TCB_IMGPSScanX.Get_imgdpi: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_scancolor: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_imgdpi(const Value: WideString);
+begin
+ if Value ='' then
+ begin
+ FImgDPI := 300;
+ ScanDpi := FImgDPI;
+ end
+ else
+ begin
+ FImgDPI := StrToInt(Value);
+ ScanDpi := FImgDPI;
+ Def_ScanDpi := FImgDPI;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.Set_scancolor(const Value: WideString);
+begin
+ if value='' then
+ begin
+ FScanColor := 0;
+ ScanColor := ifBlackWhite;
+ end
+ else
+ begin
+ FScanColor := StrToInt(Value);
+ ScanColor := ifBlackWhite;
+ end;
+
+ if FScanColor = 1 then
+ begin
+ ScanColor := ifGray256 ;
+ end;
+
+ if FScanColor = 2 then
+ begin
+ ScanColor := ifTrueColor ;
+ end;
+
+end;
+
diff --git a/separate/scanImp/CB_IMGPSScanImp_Scan.ts b/separate/scanImp/CB_IMGPSScanImp_Scan.ts
new file mode 100644
index 0000000..a9d5dcf
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Scan.ts
@@ -0,0 +1,124 @@
+import * as fs from 'fs'; import * as path from 'path';
+export function applyScanMixins(cls:any){
+ cls.prototype.StatrTwainScan=function(){
+ if(!this.Scanner.IsConfigured){this.ShowMessage(this._Msg('TWAIN 掃瞄驅動尚未安裝'));return;}
+ let ScanInfo={MultiPage:true,ImageCount:0,Graphic:new this.TTiffGraphic()};
+ try{this.ISB=null;this.Scanner.RequestedXDpi=this.ScanDpi;this.Scanner.RequestedYDpi=this.ScanDpi;this.Scanner.RequestedImageFormat=this.ScanColor;this.Scanner.ShowUI=this.TwainShowUI;
+ try{this.Scanner.OpenSource();this.Scanner.Duplex=this.ScanDuplex;if(this.FMode==='SAMPLESCAN')this.Scanner.Duplex=false;if(this.ScanImgSetUse){this.Scanner.ScanBrightness=this.ScanBright;this.Scanner.ScanContrast=this.ScanContrast;}}catch(e){this.Showmessage(this._Msg('掃瞄器發生錯誤!!'));this.Scanner.CloseSource();return;}
+ try{this.Scanner.AcquireWithSourceOpen(this.OnAcquire.bind(this),ScanInfo);}catch(e){this.Scanner.CloseSource();}}finally{this.Scanner.CloseSource();ScanInfo.Graphic.Free();}
+ };
+ cls.prototype.OnAcquire=function(DibHandle:any,XDpi:any,YDpi:any,CallBackData:any){ this.PageEnd(); this.PageDone(); };
+ cls.prototype.PageDone=function(){
+ this.ScanInfo.ImageCount++; let ISB;
+ if(this.ScanMode==='smNew'){if(this.ScanImgShowMode===0||this.ScanImgShowMode===1){ISB=this.FindISB2View(this.VMode);ISB.AntiAliased=this.ScanImgShowMode===0;ISB.ZoomMode='zmFittopage';ISB.LoadFromFile(this.PEFileName,1);}}
+ else if(this.ScanMode==='smReplace'){this.DisplayISB.LoadFromFile(this.PEFileName,1);}
+ else if(this.ScanMode==='smInsert'||this.ScanMode==='smSample'){ISB=this.FindISB2View(this.VMode);ISB.ZoomMode='zmFittopage';ISB.LoadFromFile(this.PEFileName,1);}
+ };
+ cls.prototype.PageEnd=function(){
+ if(this.ScanMode==='smNew'){
+ this.ScanSaveFilename='';let FormID=this.BarCode2FormID();
+ if(FormID!==''&&this.ISDivPageFormID(FormID))this.NowDivPageFormID=FormID;
+ if(FormID!==''&&this.ISGuideFormID(FormID))this.NowGuideFormID=FormID;
+ if(!this.FindDivFormCode(FormID)&&this.NowGuideFormID!=='')FormID=this.NowGuideFormID;
+ let DocNo=this.FormCode2DocNo(FormID);
+ if(FormID!==''&&this.FindDivFormCode(FormID)&&this.NowDivPageFormID!==''){
+ this.ScanInfo.ImageCount=0;this.ClearView(1);this.ContextList.Clear();this.Context_DocnoList.Clear();this.ClearCaseIndex();this.ScanCaseno=this.BarCode2CaseID();this.NowGuideFormID='';this.NowDivPageFormID='';
+ }
+ if(this.ScanCaseno==='')this.ScanCaseno=this.GetNoNameCase(this.ImageSavePath);
+ this.ImageSavePath=this.ImagePath;
+ if(this.ScanInfo.ImageCount===0&&fs.existsSync(path.join(this.ImageSavePath,this.ScanCaseno))){this._DelTree(path.join(this.ImageSavePath,this.ScanCaseno));this.SetCaseList('D',-1,this.ScanCaseno);}
+ this.ScanPath=path.join(this.ImageSavePath,this.ScanCaseno);this.Str2Dir(this.ScanPath);
+ this.ScanDocDir=this.FindLastestDocDir(this.ScanCaseno,DocNo);
+ if(this.DocNoNeedDiv(DocNo)){if((this.FormCode2Page(FormID)==='01'&&this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)>0)||this.ScanDocDir==='')this.ScanDocDir=this.DocNo2DocNoDir(path.join(this.ImageSavePath,this.ScanCaseno),DocNo);}
+ else{this.ScanDocDir=DocNo!==''?DocNo:this.DocNo2DocNoDir(path.join(this.ImageSavePath,this.ScanCaseno),DocNo);}
+ if(this.FirstDocDir==='')this.FirstDocDir=this.ScanDocDir;
+ this.ScanPath=path.join(this.ImageSavePath,this.ScanCaseno,this.ScanDocDir);
+ if(!fs.existsSync(this.ScanPath)&&this.ScanDocDir!==this.AttName)this.SetDocNoList('A',-1,this.ScanCaseno,this.ScanDocDir,'1');
+ this.Str2Dir(this.ScanPath);
+ this.ScanSaveFilename=FormID===''?this.Add_Zoo(this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)+1,3)+this.Ext:this.Add_Zoo(this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)+1,3)+'_'+FormID+this.Ext;
+ if(!this.FindNoSaveBarCode()){if(this.ScanInfo.ImageCount===0){this.SetCaseList('A',-1,this.ScanCaseno);this.WriteCaseIndex(path.join(this.ImageSavePath,this.ScanCaseno));}this.SetContextList('A',-1,this.ScanCaseno,this.ScanDocDir,this.ScanSaveFilename);this.PEFileName=path.join(this.ScanPath,this.ScanSaveFilename);}
+ } else if(this.ScanMode==='smReplace') {
+ if(this.ScanInfo.ImageCount===0){fs.unlinkSync(path.join(this.ScanPath,this.ScanSaveFilename));this.PEFileName=path.join(this.ScanPath,this.ScanSaveFilename);}
+ } else if(this.ScanMode==='smInsert') {
+ this.ScanSaveFilename='';let FormID=this.BarCode2FormID();if(FormID!==''&&this.ISGuideFormID(FormID))this.NowGuideFormID=FormID;if(this.NowGuideFormID!=='')FormID=this.NowGuideFormID;
+ let DocNo=this.FormCode2DocNo(FormID);this.ScanDocDir=this.FindLastestDocDir(this.ScanCaseno,DocNo);
+ if(this.FMode==='ESCAN'&&this.FModeName===this._Msg('補件掃描'))this.ScanDocDir=this.FindLastestDocDirForPage(this.ScanCaseno,DocNo,FormID);
+ if(this.DocNoNeedDiv(DocNo)){if((this.FormCode2Page(FormID)==='01'&&this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)>0)||this.ScanDocDir===''){this.ScanInfo.ImageCount=0;this.ScanDocDir=this.DocNo2DocNoDir(path.join(this.ImageSavePath,this.ScanCaseno),DocNo);}}
+ else{this.ScanDocDir=DocNo!==''?DocNo:this.DocNo2DocNoDir(path.join(this.ImageSavePath,this.ScanCaseno),DocNo);}
+ if(this.FirstDocDir==='')this.FirstDocDir=this.ScanDocDir;
+ this.ScanPath=path.join(this.ImageSavePath,this.ScanCaseno,this.ScanDocDir);
+ if(!fs.existsSync(this.ScanPath)&&this.ScanDocDir!=='Attach'&&this.ScanDocDir!=='S_Attach')this.SetDocNoList('A',-1,this.ScanCaseno,this.ScanDocDir,'1');
+ this.Str2Dir(this.ScanPath);
+ this.ScanSaveFilename=FormID===''?this.Add_Zoo(this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)+1,3)+this.Ext:this.Add_Zoo(this.GetDocDir_Page(this.ScanCaseno,this.ScanDocDir)+1,3)+'_'+FormID+this.Ext;
+ this.SetContextList('A',-1,this.ScanCaseno,this.ScanDocDir,this.ScanSaveFilename);this.PEFileName=path.join(this.ScanPath,this.ScanSaveFilename);
+ } else if(this.ScanMode==='smSample') {
+ if(this.ScanInfo.ImageCount===0){fs.unlinkSync(path.join(this.ScanPath,this.ScanSaveFilename));this.PEFileName=path.join(this.ScanPath,this.ScanSaveFilename);let BarStr='';for(let i=1;i<=this.MpsBarCodeinf.Count;i++)BarStr+=this.MpsBarCodeinf.Text[i];this.Showmessage(this._Msg('辨識到的BarCode:\n')+BarStr);}
+ }
+ };
+ cls.prototype.R_W_Scanini=function(m:string){
+ let ini=new this.Tinifile(path.join(this.ScaniniPath,'FBScan.ini'));
+ if(m==='R'){this.DeviceDelete=ini.ReadBool('DeviceDelete','Mode',this.Def_DeviceDelete);this.DeviceDeleteSize=ini.ReadInteger('DeviceDelete','Size_New',this.Def_DeviceDeleteSize);this.ScannerReverse=ini.ReadBool('Scanner','Reverse',this.Def_ScannerReverse);this.BoardClear=ini.ReadBool('Scanner','BoardClear',this.Def_BoardClear);this.ScanRotate=ini.ReadInteger('Scanner','ScanRotate',this.Def_ScanRotate);this.ScanDeskew=ini.ReadBool('Scanner','ScanDeskew',this.Def_ScanDeskew);this.ScanBright=ini.ReadInteger('Scanner','ScanBright',this.Def_ScanBright);this.ScanContrast=ini.ReadInteger('Scanner','ScanContrast',this.Def_ScanContrast);this.ScanImgShowMode=ini.ReadInteger('Scanner','ScanImgShowMode',this.Def_ScanImgShowMode);this.ScanImgSetUse=ini.ReadBool('Scanner','ScanImgSetUse',this.Def_ScanImgSetUse);}
+ else if(m==='W'){ini.WriteBool('DeviceDelete','Mode',this.DeviceDelete);ini.WriteInteger('DeviceDelete','Size_New',this.DeviceDeleteSize);ini.WriteBool('Scanner','Reverse',this.ScannerReverse);ini.WriteBool('Scanner','BoardClear',this.BoardClear);ini.WriteInteger('Scanner','ScanRotate',this.ScanRotate);ini.WriteBool('Scanner','ScanDeskew',this.ScanDeskew);ini.WriteInteger('Scanner','ScanBright',this.ScanBright);ini.WriteInteger('Scanner','ScanContrast',this.ScanContrast);ini.WriteInteger('Scanner','ScanImgShowMode',this.ScanImgShowMode);ini.WriteBool('Scanner','ScanImgSetUse',this.ScanImgSetUse);}
+ ini.Free();
+ };
+ cls.prototype.GetDefScanIni=function(){
+ this.Def_DeviceDelete=true;this.Def_DeviceDeleteSize=3072;this.Def_ScannerReverse=false;this.Def_BoardClear=false;this.Def_ScanDpi=300;this.Def_ScanDuplex=true;this.Def_ScanRotate=0;this.Def_ScanDeskew=false;this.Def_ScanImgSetUse=false;this.Def_ScanBright=0;this.Def_ScanContrast=0;this.Def_ScanImgShowMode=2;
+ for(let i=0;i<this.WORK_INF_List.Count;i++){
+ let pn=this.GetSQLData(this.WORK_INF_List,'PARA_NO',i),pc=this.GetSQLData(this.WORK_INF_List,'PARA_CONTENT',i);
+ if(pn==='SCAN_BLANKDEL_USE')this.Def_DeviceDelete=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_BLANKDEL_SIZE')this.Def_DeviceDeleteSize=pc===''?0:parseInt(pc);
+ else if(pn==='SCAN_REVERSE')this.Def_ScannerReverse=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_BOARDCLEAR')this.Def_BoardClear=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_DPI')this.Def_ScanDpi=pc===''?300:parseInt(pc);
+ else if(pn==='SCAN_DUPLEX')this.Def_ScanDuplex=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_ROTATE_MODE')this.Def_ScanRotate=pc==='1'?270:pc==='2'?180:pc==='3'?90:0;
+ else if(pn==='SCAN_DESKEW')this.Def_ScanDeskew=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_IMGSET_USE')this.Def_ScanImgSetUse=pc.toUpperCase()==='Y';
+ else if(pn==='SCAN_BRIGHT')this.Def_ScanBright=pc===''?0:parseInt(pc);
+ else if(pn==='SCAN_CONTRAST')this.Def_ScanContrast=pc===''?0:parseInt(pc);
+ else if(pn==='SCAN_SHOW_MODE')this.Def_ScanImgShowMode=pc==='0'?0:pc==='1'?1:2;
+ else if(pn==='CASE_IN_TIME')this.ScanDenialTime=pc;
+ else if(pn==='SCAN_HINT')this.ScanDenialHint=pc;
+ else if(pn==='NO_SAVE_FORM_ID')this.NoSaveBarCodeList.CommaText=pc;
+ else if(pn==='LOCAL_PATH')this.ImagePath=pc;
+ else if(pn.toUpperCase()==='GUIDEFORMID')this.GuideFormIDList.CommaText=pc;
+ else if(pn.toUpperCase()==='DIVPAGEFORMID')this.DivPageFormIDList.CommaText=pc;
+ else if(pn.toUpperCase()==='FILE_COMPRESSION')this.FJpgCompression=parseInt(pc);
+ else if(pn.toUpperCase()==='MAX_UPLOAD_SIZE')this.FMaxUploadSize=pc;
+ }
+ this.ScanDuplex=this.Def_ScanDuplex;
+ };
+ cls.prototype.EnableImage=function(v:number,s:any){this.DesableImage();let bmp=new this.TBitmap();this.ImageList3.GetBitmap(v,bmp);s.Glyph.Assign(bmp);bmp.Free();this.ViewMouseMode(v);};
+ cls.prototype.DesableImage=function(){this.NowClick=-1;let bmp=new this.TBitmap();for(let i=0;i<=6;i++){this.ImageList4.GetBitmap(i,bmp);this.FindComponent('FC'+i).Glyph.Assign(bmp);bmp.Width=0;bmp.Handle=0;}bmp.Free();this.ViewMouseMode(this.NowClick);};
+ cls.prototype.DeleteImageFile=function(p:string,f:string,c:string){if(fs.existsSync(path.join(p,f)))fs.unlinkSync(path.join(p,f));let d=this.Path2DocDir(p,c);this.SetContextList('D',-1,c,d,f);};
+ cls.prototype.DeleteDocNoFileForESCAN=function(p:string,d:string){
+ let r=false;
+ for(let i=this.ContextList.Count-1;i>=0;i--){
+ let f=this.ContextList.Strings[i];
+ if(this.FormCode2DocNo(this.FileName2FormCode(f))===d||d===this.AttName){
+ if(!this.ISExistImg(path.join(p,f))){fs.unlinkSync(path.join(p,f));this.ContextList.Delete(i);} r=true;
+ }
+ }
+ this.ContextList.SaveToFile(path.join(p,'Context.dat'));this.ContextList.LoadFromFile(path.join(p,'Context.dat'));
+ if(this.ContextList.Count===0){this._DelTree(p);this.SetDocNoList('D',-1,this.NowCaseNo,this.NowDocDir,'');} return r;
+ };
+ cls.prototype.DownLoadImage=function(p:string,c:string){return true;};
+ cls.prototype.CaseResort2Scanlist=function(p:string){
+ let S=new this.TStringlist(),S1=new this.TStringlist();if(fs.existsSync(path.join(p,'Context.dat')))S.LoadFromFile(path.join(p,'Context.dat'));
+ let x=0;
+ for(let i=1;i<this.FORM_INF_List.Count;i++){let fi=this.GetSQLData(this.FORM_INF_List,'T1.FORM_ID',i);if(this.FormCode2FileName(fi,S)==='')continue;let dt=this.GetSQLData(this.FORM_INF_List,'T2.DOC_TYPE',i);for(let n=0;n<S.Count;n++){if(S.Strings[n][0]!=='*'&&this.FileName2FormCode(S.Strings[n])===fi&&dt==='1'){x++;let on=S.Strings[n];let nn=this.Add_Zoo(S.Count+x,3)+this.FileName2NoQuene_Filename(on);S.Strings[n]='*'+S.Strings[n];S1.Add(`${on},${nn}`);}}}
+ for(let i=0;i<this.FORM_INF_List.Count;i++){let fi=this.GetSQLData(this.FORM_INF_List,'T1.FORM_ID',i);if(this.FormCode2FileName(fi,S)==='')continue;let dt=this.GetSQLData(this.FORM_INF_List,'T2.DOC_TYPE',i);for(let n=0;n<S.Count;n++){if(S.Strings[n][0]!=='*'&&this.FileName2FormCode(S.Strings[n])===fi&&dt==='2'){x++;let on=S.Strings[n];let nn=this.Add_Zoo(S.Count+x,3)+this.FileName2NoQuene_Filename(on);S.Strings[n]='*'+S.Strings[n];S1.Add(`${on},${nn}`);}}}
+ for(let i=0;i<S.Count;i++){if(S.Strings[i][0]!=='*'){x++;let on=S.Strings[i];let nn=this.Add_Zoo(S.Count+x,3)+this.FileName2NoQuene_Filename(on);S.Strings[i]='*'+S.Strings[i];S1.Add(`${on},${nn}`);}}
+ S.Clear();for(let i=0;i<S1.Count;i++){let v=S1.Strings[i].indexOf(',');let nn=S1.Strings[i].substring(v+1);S.Add(nn);S.SaveToFile(path.join(p,'scanlist.dat'));}
+ this.ReSortFileName2Scanlist(p);S.Free();S1.Free();
+ };
+ cls.prototype.GetSelectImageFile=function(){this.NowSelectFileList.Clear();for(let i=0;i<this.ComponentCount;i++){if(this.Components[i] instanceof this.TShape&&this.Components[i].Name.startsWith('SP')){let isn=this.ShapeName2PreViewISBName(this.Components[i]);let isb=this.FindComponent(isn);this.NowSelectFileList.Add(isb.FileName);}}};
+ cls.prototype.ParserPoint=function(s:string){let p=new this.TStringlist();p.Text=s;if(p.Count!==6){this.UpLPoint={X:0,Y:0};this.UpRPoint={X:0,Y:0};this.DownLPoint={X:0,Y:0};this.DownRPoint={X:0,Y:0};this.Point_Width='0';this.Point_Height='0';}else{this.UpLPoint=this.Str2Point(p.Strings[0]);this.DownLPoint=this.Str2Point(p.Strings[1]);this.UpRPoint=this.Str2Point(p.Strings[2]);this.DownRPoint=this.Str2Point(p.Strings[3]);this.Point_Width=p.Strings[4];this.Point_Height=p.Strings[5];}p.Free();};
+ cls.prototype.CheckScanDenialTime=function(){let nt=this.GetBalance2Time(this.Balance);nt=nt.substring(0,2)+':'+nt.substring(2,4)+':'+nt.substring(4,6);let r=true;if(this.ScanDenialTime!=='')if(this.StrtoTime(nt)>=this.StrtoTime(this.ScanDenialTime))r=false;return r;};
+ cls.prototype.initkscan=function(){this.ScanDuplexCB.Enabled=false;if(this.Scanner.IsConfigured){try{this.Scanner.OpenSource();if(this.Scanner.DuplexCap>0)this.ScanDuplexCB.Enabled=true;}catch(e){this.DataLoading(false,true);return;}this.Scanner.CloseSource();}};
+ cls.prototype.CheckNeedCrop=function(g:any){let fc=0;if(g.Width>(4*g.XDotsPerInch)){for(let i=1;i<=this.MpsBarcodeinf.Count;i++)if(this.MpsBarcodeinf.Text[i].length===this.FormIDLength&&this.FormIDExists(this.MpsBarcodeinf.Text[i],false,0))fc++;}return fc===2;};
+ cls.prototype.MoveImage=function(p:string,m:number){let fl=new this.TStringlist(),df=new this.TStringlist();fl.LoadFromFile(path.join(p,'Context.dat'));for(let i=0;i<fl.Count;i++){fs.renameSync(path.join(p,fl.Strings[i]),path.join(p,'@'+fl.Strings[i]));fl.Strings[i]='@'+fl.Strings[i];}for(let i=0;i<this.ComponentCount;i++){if(this.Components[i] instanceof this.TShape&&this.Components[i].Name.startsWith('SP')){let inx=parseInt(this.Components[i].Name.substring(2));df.Add(fl.Strings[inx-1]);}}for(let i=0;i<df.Count;i++){for(let n=0;n<fl.Count;n++)if(fl.Strings[n]===df.Strings[i]){fl.Delete(n);break;}}for(let i=0;i<df.Count;i++)fl.Insert(m-1+i,df.Strings[i]);fl.SaveToFile(path.join(p,'Context.dat'));this.ReSortFileName(p);this.TreeView1Click(this);fl.Free();df.Free();};
+ cls.prototype.FileName2ScanPage=function(f:string){let n=path.basename(f),v=n.indexOf('_');if(v===-1)v=n.indexOf('.');return parseInt(n.substring(0,v));};
+ cls.prototype.ReSortFileName2Scanlist=function(p:string){let s=new this.TStringlist();if(fs.existsSync(path.join(p,'scanlist.dat')))s.LoadFromFile(path.join(p,'scanlist.dat'));for(let i=0;i<s.Count;i++)s.Strings[i]=this.Add_Zoo(i+1,3)+this.FileName2NoQuene_Filename(s.Strings[i]);s.SaveToFile(path.join(p,'scanlist.dat'));s.Free();};
+ cls.prototype.Get_imgdpi=function(){return this.FImgDPI.toString();};cls.prototype.Get_scancolor=function(){return this.FScanColor.toString();};cls.prototype.Set_imgdpi=function(v:string){this.FImgDPI=v===''?300:parseInt(v);this.ScanDpi=this.FImgDPI;this.Def_ScanDpi=this.FImgDPI;};cls.prototype.Set_scancolor=function(v:string){this.FScanColor=v===''?0:parseInt(v);this.ScanColor=this.FScanColor===2?'ifTrueColor':(this.FScanColor===1?'ifGray256':'ifBlackWhite');};
+}
diff --git a/separate/scanImp/CB_IMGPSScanImp_UI.pas b/separate/scanImp/CB_IMGPSScanImp_UI.pas
new file mode 100644
index 0000000..d4378ac
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_UI.pas
@@ -0,0 +1,6592 @@
+procedure TCB_IMGPSScanX.WMMOUSEWHEEL(var message: TWMMouseWheel);
+var
+ I: Integer;
+ iISB : TImageScrollBox;
+begin
+ inherited;
+ //lb1.Caption:=IntToStr(message.Keys);
+ if (message.WheelDelta = WHEEL_DELTA) Then
+ begin
+
+ if ScrollBox1.Focused then
+ begin
+ ScrollBox1.VertScrollBar.Increment := 50;
+ ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
+ end;
+ if DisplayISB <> nil then
+ begin
+ if (DisplayISB.Focused) and (message.Keys=0) then
+ begin
+ DisplayISB.VertScrollBar.Increment := 50;
+ DisplayISB.Perform(WM_VSCROLL,SB_Lineup,0);
+ end;
+
+ if (DisplayISB.Focused) and (message.Keys=50) then
+ begin
+ DisplayISB.ZoomMode := zmPercent;
+ if DisplayISB.ZoomPercent < 90 then
+ DisplayISB.ZoomPercent := DisplayISB.ZoomPercent+10;
+ end;
+
+ end;
+ i:=0;
+ while FindComponent(ISBName+inttostr(i)) <> nil do
+ begin
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
+ if iISB.Focused then
+ begin
+ ScrollBox1.VertScrollBar.Increment := 50;
+ ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
+ end;
+ inc(i);
+ end;
+
+ end
+ else if (message.WheelDelta = -WHEEL_DELTA) then
+ begin
+
+ if ScrollBox1.Focused then
+ begin
+ ScrollBox1.VertScrollBar.Increment := 50;
+ ScrollBox1.Perform(WM_VSCROLL, SB_LINEDOWN, 0);
+ end;
+ if DisplayISB <> nil then
+ begin
+ if (DisplayISB.Focused) and (message.Keys=0) then
+ begin
+ DisplayISB.VertScrollBar.Increment := 50;
+ DisplayISB.Perform(WM_VSCROLL,SB_LINEDOWN,0);
+ end;
+ if (DisplayISB.Focused) and (message.Keys=50) then
+ begin
+ DisplayISB.ZoomMode := zmPercent;
+ if DisplayISB.ZoomPercent > 10 then
+ DisplayISB.ZoomPercent := DisplayISB.ZoomPercent-10;
+ end;
+
+
+ end;
+
+ i:=0;
+ while FindComponent(ISBName+inttostr(i)) <> nil do
+ begin
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
+ if iISB.Focused then
+ begin
+ ScrollBox1.VertScrollBar.Increment := 50;
+ ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
+ end;
+ inc(i);
+ end;
+
+ end;
+
+
+end;
+
+procedure TCB_IMGPSScanX.WNoteBtnClick(Sender: TObject);
+var
+ i,n,v,v1:Integer;
+ SortMemoForm : TSortMemoForm;
+ M_Content,M_ID,M_Name : String;
+ S : TStringlist;
+begin
+ ShowText := _Msg('備註輸入中,請稍候');
+ DataLoading(True,True);
+ SortMemoForm := TSortMemoForm.Create(Self);
+ S := TStringlist.Create;
+ try
+ InitialLanguage(SortMemoForm); //載入多國語言
+
+ SortMemoForm.ContentList := TStringlist.Create; //註記內容
+ SortMemoForm.MemoIDList := TStringlist.Create; //註記代號
+ SortMemoForm.MemoNameList := TStringlist.Create; //註記名稱
+
+ for i := 1 to MEMO_INF_List.Count - 1 do
+ begin
+ M_Content := GetSQLData(MEMO_INF_List,'T1.MEMO_CONTENT',i);
+ M_ID := GetSQLData(MEMO_INF_List,'T1.MEMO_TYPE',i);
+ M_Name := GetSQLData(MEMO_INF_List,'T2.MEMO_TYPE_NAME',i);
+ SortMemoForm.ComboBox1.Items.Add(M_Name+'-->'+M_Content);
+ SortMemoForm.ContentList.Add(M_Content); //註記內容
+ SortMemoForm.MemoIDList.Add(M_ID); //註記代號
+ SortMemoForm.MemoNameList.Add(M_Name); //註記名稱
+ end;
+ if FileExists(DisplayPath+'Scan_Memo.dat') then
+ begin
+ S.LoadFromFile(DisplayPath+'Scan_Memo.dat');
+ for I := 0 to S.Count - 1 do
+ begin
+ v := Pos(',',S.Strings[i]);
+ v1 := length(S.Strings[i]);
+ M_ID := copy(S.Strings[i],1,v-1);
+ M_Name := MemoInfoTransfer('ID',M_ID,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList);
+ M_Content := copy(S.Strings[i],v+1,v1-v);
+ SortMemoForm.ResoureMemo.Add(M_Name+'-->'+M_Content);
+ With SortMemoForm.MemoLV.Items.Add do
+ begin
+ Caption := M_Content;
+ SubItems.Add(M_Name);
+ end;
+ end;
+ end;
+
+ if SortMemoForm.ShowModal = mrOk then
+ begin
+ S.Clear;
+ for I := 0 to SortMemoForm.MemoLV.Items.Count - 1 do
+ begin
+ M_Content := SortMemoForm.MemoLV.Items.Item[i].Caption;
+ M_Name := SortMemoForm.MemoLV.Items.Item[i].SubItems.Strings[0];
+ M_ID := MemoInfoTransfer('NAME',M_Name,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList);
+ S.Add(M_ID+','+M_Content);
+ end;
+ S.SaveToFile(DisplayPath+'Scan_Memo.dat');
+ end;
+ SortMemoForm.ContentList.Free; //註記內容
+ SortMemoForm.MemoIDList.Free; //註記代號
+ SortMemoForm.MemoNameList.Free; //註記名稱
+ finally
+ SortMemoForm.Free;
+ S.Free;
+ DataLoading(False,False);
+ if Ch_WriteNote then
+ begin
+ Ch_WriteNote := False;
+ CaseHelpBtnClick(self);
+ ErrIndex := 0;
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.EventSinkChanged(const EventSink: IUnknown);
+begin
+ FEvents := EventSink as ICB_IMGPSScanXEvents;
+ inherited EventSinkChanged(EventSink);
+end;
+
+procedure TCB_IMGPSScanX.FC0Click(Sender: TObject);
+begin
+ IF NowClick = 0 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(0 ,Sender);
+ NowClick := 0;
+end;
+
+procedure TCB_IMGPSScanX.FC1Click(Sender: TObject);
+begin
+ IF NowClick = 1 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(1 ,Sender);
+ NowClick := 1;
+end;
+
+procedure TCB_IMGPSScanX.FC2Click(Sender: TObject);
+begin
+ IF NowClick = 2 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(2,Sender);
+ NowClick := 2;
+end;
+
+procedure TCB_IMGPSScanX.FC3Click(Sender: TObject);
+begin
+ IF NowClick = 3 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(3 ,Sender);
+ NowClick := 3;
+end;
+
+procedure TCB_IMGPSScanX.FC4Click(Sender: TObject);
+begin
+ IF NowClick = 4 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(4 ,Sender);
+ NowClick := 4;
+end;
+
+procedure TCB_IMGPSScanX.FC5Click(Sender: TObject);
+begin
+ IF NowClick = 5 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(5 ,Sender);
+ NowClick := 5;
+end;
+
+procedure TCB_IMGPSScanX.FC6Click(Sender: TObject);
+begin
+ {IF NowClick = 6 Then
+ begin
+ DesableImage;
+ Exit;
+ end;
+ EnableImage(6 ,Sender);
+ NowClick := 6;}
+ PM605Click(nil);
+end;
+
+procedure TCB_IMGPSScanX.ISB1Click(Sender: TObject);
+var
+ p : Integer;
+begin
+ DisplayISB := TImageScrollBox(Sender);
+ Shape1.Left := TPanel(TImageScrollBox(Sender).Parent).Left - Seg;
+ Shape1.Top := TPanel(TImageScrollBox(Sender).Parent).Top - Seg;
+ P := strtoint(copy(DisplayISB.Name,4,1)) + ScrollBar1.Position-2;
+ if P <= PageLV.Items.Count-1 then
+ begin
+ if PageLVclear then
+ begin
+ PageLV.ClearSelection;
+ end;
+ NowPage := p+1;
+ PageLV.ItemIndex := P;
+ end;
+ //DisplayISB.SetFocus;
+end;
+
+procedure TCB_IMGPSScanX.ISB1EndScroll(Sender: TObject);
+var
+ ISB : TImageScrollBox;
+begin
+ ISB := TImageScrollBox(Sender);
+
+ SetScrollData(ISB,ISB.HorzScrollBar.Position,ISB.VertScrollBar.Position,ISB.ZoomPercent);
+ {if (TImageScrollBox(Sender) = MpsViewX1) and SortMode then
+ begin
+ ReczoomPercent := MpsViewX1.ZoomPercent;
+ RecHozPos := MpsViewX1.HorzScrollBarPos;
+ RecVerPos := MpsViewX1.VertScrollBarPos;
+ end;}
+end;
+
+procedure TCB_IMGPSScanX.ISB1ImageMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+var
+ p : Integer;
+begin
+ DisplayISB := TImageScrollBox(Sender);
+ if NowClick<>0 then
+ DisplayISB.SetFocus;
+ Shape1.Left := TPanel(TImageScrollBox(Sender).Parent).Left - Seg;
+ Shape1.Top := TPanel(TImageScrollBox(Sender).Parent).Top - Seg;
+ P := strtoint(copy(DisplayISB.Name,4,1)) + ScrollBar1.Position-2;
+ if P <= PageLV.Items.Count-1 then
+ begin
+ NowPage := p+1;
+ PageLV.ClearSelection;
+ PageLV.ItemIndex := P;
+
+ //PageLV.Selected := PageLV.Items.Item[PageLV.ItemIndex];
+
+ end;
+ if (NowClick = -1) and (Button=TMouseButton(mbLeft)) and (DisplayISB.FileName <> '') then
+ begin
+ {for P := 1 to 8 do
+ begin
+ TImageScrollBox(FindComponent('ISB'+inttostr(p))).Enabled := False;
+ end; }
+ DisplayISB.BeginDrag(True);
+ end;
+ case TImageScrollBox(Sender).MouseMode of
+ mmR90,mmR180,mmR270:
+ begin
+ TImageScrollBox(Sender).LoadFromFile(TImageScrollBox(Sender).FileName,1);
+ end;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.ISB1ImageMouseMove(Sender: TObject; Shift: TShiftState;
+ X, Y: Integer);
+begin
+ //Edit1.SetFocus;
+ //TImageScrollBox(Sender).SetFocus;
+
+ if TImageScrollBox(Sender).FileName = '' then
+ TImageScrollBox(Sender).MouseMode := mmUser
+ Else
+ ViewMouseMode(NowClick);
+
+ ISB1.AlwaysShowAnnotations := False;
+
+// if TImageScrollBox(Sender).FileName = '' then
+// begin
+////ShowMessage('AAA');
+//Label3.Caption:='FileName='+TImageScrollBox(Sender).FileName+' time='+FormatDateTime('yyyy/mm/dd HH:MM:SS', now);
+// TImageScrollBox(Sender).MouseMode := mmUser
+// end
+// Else
+// begin
+//Label3.Caption:='FileName='+TImageScrollBox(Sender).FileName;
+// ViewMouseMode(NowClick);
+// end;
+end;
+
+procedure TCB_IMGPSScanX.ISB1ImageMouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+Var
+ p : Integer;
+ ISB : TImageScrollBox;
+begin
+ case TImageScrollBox(Sender).MouseMode of
+ mmDelete:
+ begin
+ PM508Click(Self);
+ end;
+ mmR90,mmR180,mmR270:
+ begin
+ if TImageScrollBox(Sender).Graphic.ImageFormat <> ifBlackWhite then
+ begin
+ TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;
+ TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveToFile(TImageScrollBox(Sender).FileName);
+ end
+ Else
+ TImageScrollBox(Sender).SaveToFile(TImageScrollBox(Sender).FileName);
+
+ SelectISB.Graphic.Assign(TImageScrollBox(Sender).Graphic);
+ SelectISB.Redraw(True);
+ FitPreViewISB;
+ ISBClick(SelectISB);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ end;
+ end;
+
+ ISB := TImageScrollBox(Sender);
+ if (ISB.MouseMode = mmZoom) or (ISB.MouseMode = mmDrag) then
+ SetScrollData(ISB,ISB.HorzScrollBar.Position,ISB.VertScrollBar.Position,ISB.ZoomPercent);
+
+end;
+
+function TCB_IMGPSScanX.Get_AutoScroll: WordBool;
+begin
+ Result := AutoScroll;
+end;
+
+function TCB_IMGPSScanX.Get_KeyPreview: WordBool;
+begin
+ Result := KeyPreview;
+end;
+
+function TCB_IMGPSScanX.Get_MouseInClient: WordBool;
+begin
+ Result := MouseInClient;
+end;
+
+procedure TCB_IMGPSScanX.ActivateEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnActivate;
+end;
+
+procedure TCB_IMGPSScanX.ClickEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnClick;
+end;
+
+procedure TCB_IMGPSScanX.CreateEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnCreate;
+end;
+
+procedure TCB_IMGPSScanX.DblClickEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnDblClick;
+end;
+
+procedure TCB_IMGPSScanX.DeactivateEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnDeactivate;
+end;
+
+procedure TCB_IMGPSScanX.DestroyEvent(Sender: TObject);
+begin
+ //********清單區********
+ Doc_Inf_List.Free; //Doc_Inf 清單 Docno + 版本為key
+ DM_FORM_INF_List.Free; //DM_FORM_INF 清單 Docno + 版本為key
+ FORM_INF_List.Free; //FORM_INF的清單
+ CHECK_RULE_INF_List.Free; //CHECK_RULE_INF 清單
+ MEMO_INF_List.Free; //MEMO_INF 清單
+ WORK_INF_List.Free; //WORK_INF 清單
+ LASTEST_FORM_INF_List.Free; // LASTEST_FORM_INF 清單
+ FindResult.Free ; //找SQLData的結果
+ OMRFileList.Free; //要OMR檢核的文件(只檢查每種Form的第一頁)
+ FormCode_PageSize.Free; //文件的預設大小 FormCode_Height_Width
+ DocNo_NeedDoc.Free; //有Docno時要相依的文件 DocNo_相依文件_相依文件
+ DocNo_NoDoc.Free; //有Docno時互斥的文件 DocNo_互斥文件_互斥文件
+ DocNo_VerinCase.Free; //案件裡的DocNo+版本的清單
+ CaseDocNoList.Free; //案件裡的DocNo清單
+ CaseDocNo_CopiesList.Free; //案件裡的DocNo份數清單
+ CaseList.Free; //記錄掃瞄案件的順序
+ NoSaveBarCodeList.Free; //不儲存的條碼清單
+ FormID_List.Free; //FormID清單
+ DocNo_List.Free; //DocNo清單
+ Context_DocnoList.Free; //案件裡的檔案Docno清單
+ ContextList.Free; //案件裡的檔案清單
+ AttContextList.Free; //案件裡的附加檔案清單
+ NowShowFileList.Free; //目前顯示的影像清單
+ NowSelectFileList.Free; //目前被點選的影像清單
+ Cust_DocNoList.Free; //自行定義文件名稱
+ IN_WH_DocNoList.Free; //入庫的文件清單
+ GuideFormIDList.Free; //要當導引頁表單清單
+ DivPageFormIDList.Free; //要當分案頁表單清單
+ LastInitFormidList.Free;
+ LastAddFormidList.Free;
+ SampleFormIDList.Free;
+ ExistImgList.Free;
+ reSizeExistImgList.Free;
+ //********清單區********
+ if (FMode = 'DSCAN') or (FMode = 'ESCAN') then //重掃件及異動件要只能掃指定編號的件
+ begin
+ if ImagePath<>'' then
+ _Deltree(ImagePath);
+ end;
+
+ if FEvents <> nil then FEvents.OnDestroy;
+end;
+
+procedure TCB_IMGPSScanX.KeyPressEvent(Sender: TObject; var Key: Char);
+var
+ TempKey: Smallint;
+begin
+ TempKey := Smallint(Key);
+ if FEvents <> nil then FEvents.OnKeyPress(TempKey);
+ Key := Char(TempKey);
+end;
+
+procedure TCB_IMGPSScanX.mode1Click(Sender: TObject);
+begin
+ VMode := 0;
+ GoViewMode;
+ //ScrollBar1Change(Self);
+ Panel14.Visible := False;
+end;
+
+procedure TCB_IMGPSScanX.mode2Click(Sender: TObject);
+begin
+ VMode := 1;
+ GoViewMode;
+ //ScrollBar1Change(Self);
+ Panel14.Visible := True;
+end;
+
+procedure TCB_IMGPSScanX.mode3Click(Sender: TObject);
+begin
+ VMode := 2;
+ GoViewMode;
+ ScrollBar1Change(Self);
+end;
+
+procedure TCB_IMGPSScanX.mode4Click(Sender: TObject);
+begin
+ VMode := 3;
+ GoViewMode;
+ ScrollBar1Change(Self);
+end;
+
+procedure TCB_IMGPSScanX.MouseEnterEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnMouseEnter;
+end;
+
+procedure TCB_IMGPSScanX.MouseLeaveEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnMouseLeave;
+end;
+
+procedure TCB_IMGPSScanX.PaintEvent(Sender: TObject);
+begin
+ if FEvents <> nil then FEvents.OnPaint;
+end;
+
+procedure TCB_IMGPSScanX.Set_AutoScroll(Value: WordBool);
+begin
+ AutoScroll := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_KeyPreview(Value: WordBool);
+begin
+ KeyPreview := Value;
+end;
+
+procedure TCB_IMGPSScanX.PM401Click(Sender: TObject);
+var
+ i : Integer;
+ FromIndex : Integer;
+ CaseID : String;
+ NewPath : String;
+ OldName,NewName:String;
+ S : TStringlist;
+begin
+ S := TStringlist.Create;
+ try
+ FromIndex := PageLv.ItemIndex;
+ if FromIndex = 0 then
+ begin
+ Showmessage(_Msg('不能從第1頁分案'));
+ Exit;
+ end;
+
+ If MessageDlg(Format(_Msg('是否確定從%d頁分出新案'),[PageLV.ItemIndex+1]),Mtconfirmation,[mbyes,mbcancel],0) = mrcancel Then Exit;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ CaseID := GetNoNameCase(ImageSavePath);
+ NewPath := ImageSavePath + CaseID+'\';
+ Str2Dir(NewPath);
+ for i := FromIndex to ContextList.Count - 1 do
+ begin
+ OldName := ContextList.Strings[i];
+ //NewName := Add_Zoo(S.Count+1,3)+Copy(OldName,4,length(OldName)-3);
+ NewName := Add_Zoo(S.Count+1,3)+FileName2NoQuene_Filename(OldName);
+
+ ReNameFile(DisplayPath+OldName,NewPath+NewName);
+ S.Add(NewName);
+ S.SaveToFile(NewPath+'Context.dat');
+ end;
+ for i := ContextList.Count - 1 downto FromIndex do
+ begin
+ ContextList.Delete(i);
+ ContextList.SaveToFile(DisplayPath+'Context.dat');
+ end;
+ SetCaseList('I',MyTreeNode1.IndexOf(MyTreeNode2)+1,CaseID);
+ if FileExists(DisplayPath+'CaseIndex.dat') then //把原經辦代號取出來再寫入新件裡
+ begin
+ S.LoadFromFile(DisplayPath+'CaseIndex.dat');
+ end;
+ DisplayPath := '';
+
+ ClearCaseIndex;
+ WriteCaseIndex(NewPath);
+ finally
+ S.Free;
+ end;
+ LoadImgFile;
+ Showmessage(_Msg('分案完成'));
+end;
+
+procedure TCB_IMGPSScanX.PM402Click(Sender: TObject);
+var
+ i : Integer;
+begin
+ for i := 0 to PageLV.Items.Count - 1 do
+ begin
+ PageLV.Items.Item[i].Selected := True;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PM403Click(Sender: TObject);
+var
+ i : Integer;
+begin
+ for i := 0 to PageLV.Items.Count - 1 do
+ begin
+ PageLV.Items.Item[i].Selected := False;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PM404Click(Sender: TObject);
+var
+ i : Integer;
+ DocListForm : TDocListForm;
+ OldName,NewName,Ext : String;
+ FormID,FormName : String;
+ PreNode2Name : String;
+begin
+ PreNode2Name := '';
+ if TreeView1.Selected.Parent = MyTreeNode1 then
+ PreNode2Name:= GetNode2Name(MyTreeNode2);
+ ShowText := _Msg('文件歸類中,請稍候');
+ DataLoading(True,True);
+ DocListForm := TDocListForm.Create(self);
+ try
+ InitialLanguage(PatchDlg); //載入多國語言
+ for i := 1 to FORM_INF_List.Count - 1 do
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
+ if (FormID <> NowFormCode) and FormIDExists(FormID,True,0) then
+ begin
+ DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
+ With DocListForm.DocLV.Items.Add do
+ begin
+ Caption := FormID;
+ SubItems.Add(FormName);
+ end;
+ end;
+ end;
+
+ if DocListForm.ShowModal = mrOk then
+ begin
+ FormID := DocListForm.DocLV.Selected.Caption;
+ if (TreeView1.Selected.Level=1) then
+ begin
+ PageReplaceFormID(DisplayPath,'ALL',FormID);
+ end
+ Else if (TreeView1.Selected.Level=2) and (NowFormCode = '') then
+ PageReplaceFormID(DisplayPath,'',FormID)
+ Else
+ begin
+ PageReplaceFormID(DisplayPath,NowFormCode,FormID);
+ end;
+ //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno); //201408280改
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ //Showmessage(_Msg('歸類完成')); //20101103 User要求拿掉
+ if PreNode2Name <> '' then // 回到原本點選的文件節點上
+ begin
+ for i := 0 to MyTreeNode1.Count - 1 do
+ begin
+ if GetNode2Name(MyTreeNode1.Item[i]) = PreNode2Name then
+ begin
+ TreeView1.Selected := MyTreeNode1.Item[i];
+ Break;
+ end;
+ end;
+ end;
+ TreeView1click(self);
+ end;
+ finally
+ DocListForm.Free;
+ DataLoading(False,False);
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.PM601Click(Sender: TObject);
+var
+ i : Integer;
+ DocListForm : TDocListForm;
+ OldName,NewName,Ext : String;
+ FormID,FormName,DocNo,DocDir : String;
+ PreNode2Name : String;
+ iFormID : String;
+ iISBName : String;
+ iISB : TImageScrollBox;
+ GoAtt : Boolean;
+ AttLv : Integer;
+ ST1 :TStringList;
+begin
+ PreNode2Name := '';
+ ST1:=TStringList.Create;
+ if TreeView1.Selected.Parent = MyTreeNode1 then
+ PreNode2Name:= GetNode2Name(MyTreeNode2);
+ ShowText := _Msg('文件歸類中,請稍候');
+LogFile1.LogToFile(logTimeString+'縮圖 歸類開始');
+ DataLoading(True,True);
+ GoAtt := False;
+ if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
+ begin
+ AttLv := TreeView1.Selected.Level;
+ GoAtt := True;
+ end;
+ DocListForm := TDocListForm.Create(self);
+ try
+ InitialLanguage(DocListForm); //載入多國語言
+ //InitialLanguage(PatchDlg); //載入多國語言
+ DocListForm.CheckBox1.Visible:=False;
+ for i := 1 to FORM_INF_List.Count - 1 do
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
+ DocNo := GetSQLData(FORM_INF_List,'T1.DOC_NO',i)+GetSQLData(FORM_INF_List,'T1.DOC_VERSION',i);
+ if not FormIDAppear(FormID) then Continue; //20170816 先秀全部
+
+ //Showmessage(FORM_INF_List.Text);
+ //showmessage(inttostr(FORM_INF_List.Count)+#13+inttostr(self.Doc_Inf_List.Count));
+ if (FormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(FormID,False,i) then
+ begin
+ DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
+ With DocListForm.DocLV.Items.Add do
+ begin
+ Caption := FormID;
+ SubItems.Add(FormName);
+ end;
+ end;
+ end;
+ if DocListForm.ShowModal = mrOk then
+ begin
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+ OldName := ExtractFileName(iISB.FileName);
+ Ext := ExtractFileExt(OldName);
+
+ if DocListForm.CheckBox1.Checked then
+ begin
+ FormID := DocListForm.Edit1.Text;
+ DocNo := GetNewCustomDocNo(DisplayPath,FormID);
+ end
+ else
+ begin
+ FormID := DocListForm.DocLV.Selected.Caption;
+ DocNo := FormCode2DocNo(FormID);
+ end;
+
+
+ if DocNoDir2DocNo(Path2DocDir(ExtractFilePath(iISB.FileName),NowCaseno)) = DocNo then
+ DocDir := Path2DocDir(ExtractFilePath(iISB.FileName),NowCaseNo)
+ Else
+ DocDir := FindLastestDocDir(NowCaseno,DocNo);
+
+//ShowMessage('DocNoNeedDiv(DocNo)='+BoolToStr(DocNoNeedDiv(DocNo),true));
+//ShowMessage('DocDir='+DocDir);
+
+ if DocNoNeedDiv(DocNo) then //要分份數
+ begin
+ if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(NowCaseno,DocDir)>0)) or (DocDir = '') then
+ begin
+ DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
+ end
+ else
+ begin //20171016 真對補件影響 所加的判斷
+ ST1.Clear;
+ if FileExists(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat') then
+ begin
+ ST1.LoadFromFile(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat');
+ if (ST1.Count > 0) and ISExistImg(ImageSavePath + NowCaseno+'\'+DocDir+'\'+ST1.Strings[0]) then //20181210 多增加判斷ST1>0 否則會有機會出現List out of bound Hong
+ begin
+ DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
+ end;
+ end;
+ end;
+ end
+ Else //不分份數
+ begin
+ if DocNo <> '' then
+ DocDir := DocNo
+ else //Attach 附件
+ DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
+ end;
+ if (not DirectoryExists(ImageSavePath + NowCaseno+'\'+DocDir+'\')) and (DocDir <> AttName) then
+ SetDocNoList('A',-1,NowCaseno,DocDir,'1');
+
+ {if DocDir = '' then
+ begin
+ DocDir := DocNo;
+ if DocNoNeedDiv(DocNo) then
+ DocDir:=DocNo2DocNoDir(ImageSavePath+NowCaseno+'\',DocNo);
+ SetDocNoList('A',-1,NowCaseno,DocDir);
+ end; }
+LogFile1.LogToFile(logTimeString+'縮圖 FormID='+FormID);
+ if Not DirectoryExists(ImageSavePath+NowCaseno+'\'+DocDir) then
+ Mkdir(ImageSavePath+NowCaseno+'\'+DocDir);
+ ContextList.Clear;
+ if FileExists(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat') then
+ ContextList.LoadFromFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');
+ NewName := Add_Zoo(ContextList.Count+1,3)+'_'+FormID+Ext;
+ CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
+ {ContextList.Add(NewName);
+ ContextList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat'); }
+ SetContextList('A',-1,NowCaseNo,DocDir,NewName);
+ DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
+ //RenameFile(iISB.FileName,ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);
+ //ReNameContext(iISB.FileName,OldName,NewName);
+ end;
+ end;
+//ShowMessage('KKKK');
+ ReSortFileName(ExtractFilePath(iISB.FileName));
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+
+ if GoAtt then
+ begin
+ GotoAttach(AttLv);
+ end;
+ TreeView1click(self);
+
+ end;
+ finally
+ DataLoading(False,False);
+ DocListForm.Free;
+ ST1.Free;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.PM602Click(Sender: TObject);
+var
+ FileList:TStringlist;
+ SavePath : String;
+ DocDir : String;
+ CustomDocName : String;
+ CustomDocNo : String;
+ i : Integer;
+ OldName,NewName,Ext : String;
+ FormID,FormName,DocNo : String;
+ PreNode2Name : String;
+ iFormID : String;
+ iISBName : String;
+ iISB : TImageScrollBox;
+ GoAtt : Boolean;
+ AttLv : Integer;
+begin
+ GoAtt := False;
+ if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
+ begin
+ AttLv := TreeView1.Selected.Level;
+ GoAtt := True;
+ end;
+
+ if InputQuery(_Msg('輸入其他文件名稱'),_Msg('文件名稱'),CustomDocName) then
+ begin
+ if FindCustomDocName(DisplayPath,CustomDocName) then
+ begin
+ Showmessage(Format(_Msg('文件名稱:"%s"己存在'),[CustomDocName]));
+ Exit;
+ end;
+ CustomDocNo := GetNewCustomDocNo(DisplayPath,CustomDocName);
+ end;
+ if CustomDocNo = '' then Exit;
+ DocDir := CustomDocNo;
+LogFile1.LogToFile(logTimeString+'縮圖 歸類自訂文件 DocDir='+DocDir);
+ SavePath := ImageSavePath+NowCaseNo+'\'+DocDir+'\';
+ Str2Dir(SavePath);
+ SetDocNoList('A',-1,NowCaseNo,DocDir,'1');
+ FileList := TStringlist.Create;
+ try
+ FileList.Clear;
+ if FileExists(SavePath+'Context.dat') then
+ FileList.LoadFromFile(SavePath+'Context.dat');
+
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+ OldName := ExtractFileName(iISB.FileName);
+ Ext := ExtractFileExt(OldName);
+ NewName := Add_Zoo(FileList.Count+1,3)+'_'+GetCustomFormID(ImageSavePath+NowCaseNo+'\',CustomDocNo)+ext;
+
+ //Showmessage(iISB.FileName+#13+ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);
+ CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
+ SetContextList('A',-1,NowCaseno,DocDir,NewName);
+ FileList.Add(NewName);
+ {FileList.Add(NewName);
+ FileList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');}
+ DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
+ end;
+ end;
+ finally
+ FileList.Free;
+ end;
+ ReSortFileName(ExtractFilePath(iISB.FileName));
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+
+ if GoAtt then
+ begin
+ GotoAttach(AttLv);
+ end;
+ TreeView1click(self);
+ MyTreeNode1.Expand(True);
+end;
+
+procedure TCB_IMGPSScanX.PM604Click(Sender: TObject);
+var
+ i : Integer;
+ iISBName : String;
+ iISB : TImageScrollBox;
+begin
+ //Showmessage(inttostr(ComponentCount));
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ //Showmessage(Components[i].Name);
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+ DeskewImg(iISB.Graphic);
+ iISB.Redraw(True);
+ iISB.SaveToFile(iISB.FileName);
+ DisplayISB.LoadFromFile(DisplayISB.FileName,1);
+ end;
+ end;
+ //TreeView1Click(nil);
+end;
+
+procedure TCB_IMGPSScanX.PM605Click(Sender: TObject);
+var
+ i : Integer;
+ iISBName,OldName : String;
+ iISB : TImageScrollBox;
+begin
+ if MessageDlg(_Msg('是否確定刪除??'),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+
+ for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ //Showmessage(Components[i].Name);
+ iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
+ iISB := TImageScrollBox(FindComponent(iISBName));
+//ShowMessage('iISB.FileName='+iISB.FileName);
+//ShowMessage(ExtractFilePath(iISB.FileName)+','+ExtractFileName(iISB.FileName)+','+NowCaseNo);
+// if (FMode = 'ESCAN') and (FModeName<>'異動件') then
+// begin
+// if ISExistImg(iISB.FileName) then
+// begin
+// ShowMessage(_Msg('此圖為非當次掃瞄,不可刪除'));
+// Exit;
+// end;
+// end;
+LogFile1.LogToFile(logTimeString+'縮圖刪除 iISB.FileName='+iISB.FileName);
+ DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
+ end;
+ end;
+//ShowMessage('iISB.FileName='+iISB.FileName);
+ ReSortFileName(ExtractFilePath(iISB.FileName));
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ MyTreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
+ NewTreeNodeRefresh;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ TreeView1click(self);
+end;
+
+procedure TCB_IMGPSScanX.N1Click(Sender: TObject);
+var
+ mp:string;
+begin
+ mp := InputBox(_Msg('移動頁數'),_Msg('請輸入移入頁碼'),'');
+ if (mp <> '') then
+ begin
+ MoveImage(DisplayPath+NowDocDir+'\',strtoint(mp));
+ end;
+end;
+
+procedure TCB_IMGPSScanX.N51Click(Sender: TObject);
+begin
+ VMode := 4;
+ GoViewMode;
+ ScrollBar1Change(Self);
+end;
+
+procedure TCB_IMGPSScanX.NewScanBtnClick(Sender: TObject);
+begin
+ IF not InitialOk Then
+ begin
+ Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
+ Exit;
+ end;
+LogFile1.LogToFile(logTimeString+'掃瞄開始');
+ if (FMode = 'RSCAN') or (FMode = 'ESCAN') or (FMode = 'DSCAN') then
+ begin
+ if NewTreeNode.Count > 0 then
+ begin
+ TreeView1.Selected := NewTreeNode.Item[0];
+ TreeView1click(nil);
+ FirstDocDir := '';
+ NowGuideFormID := '';
+ NowDivPageFormID :='';
+ AddScanBtnclick(nil);
+ end;
+ end
+ Else
+ begin
+ TreeView1.Selected := NewTreeNode;
+ NewTreeNode.Expand(False);
+ TreeView1Click(self);
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ ScanMode := smNew;
+ ScanInfo.ImageCount := 0;
+ ScanPath := '';
+ ScanCaseno := '';
+ NowGuideFormID := '';
+ NowDivPageFormID :='';
+ ClearView(1);
+ ContextList.Clear;
+ Try
+ StatrTwainScan;
+LogFile1.LogToFile(logTimeString+'掃瞄結束');
+ Except
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ end;
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ LoadImgFile;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.NextPageBtnClick(Sender: TObject);
+var
+ page : Integer;
+begin
+ {page := ScrollBar1.Position;
+ Case Vmode of
+ 0 : Inc(page);
+ 1 : Page := Page + 2;
+ 2 : Page := Page + 4;
+ 3 : Page := Page + 6;
+ 4 : Page := Page + 8;
+ end;
+ IF page <= ScrollBar1.Max Then
+ begin
+ ScrollBar1.Position := page;
+ end;}
+ if selectISB = nil then Exit;
+ NextPage(SelectPage);
+ if SelectISB.Parent.Top+SelectISB.Parent.Height+4 > scrollBox1.Height then
+ ScrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + (SelectISB.Parent.Top+SelectISB.Parent.Height-ScrollBox1.Height+8);
+
+end;
+
+procedure TCB_IMGPSScanX.OptionBtnClick(Sender: TObject);
+var
+ PatchDlg : TPatchDlg;
+ i : Integer;
+begin
+ IF not InitialOk Then
+ begin
+ Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
+ Exit;
+ end;
+ ShowText := _Msg('掃瞄參數設定中,請稍候');
+ DataLoading(True,True);
+
+ PatchDlg := TPatchDlg.Create(self);
+ try
+ InitialLanguage(PatchDlg); //載入多國語言
+ PatchDlg.BlankuseCB.Checked := DeviceDelete;
+ if PatchDlg.BlankuseCB.Checked then
+ PatchDlg.SpinEdit5.Enabled := True
+ else
+ PatchDlg.SpinEdit5.Enabled := False;
+ PatchDlg.SpinEdit5.Value := DeviceDeleteSize;
+ For i := 0 to PatchDlg.ComboBox1.Items.Count -1 do
+ begin
+ If inttostr(ScanDpi) = PatchDlg.ComboBox1.Items.Strings[i] Then
+ PatchDlg.ComboBox1.ItemIndex := i;
+ end;
+ PatchDlg.DuplexCB.Checked := ScanDuplex;
+ PatchDlg.ReverseCB.Checked := ScannerReverse;
+ PatchDlg.BorderCB.Checked := BoardClear;
+ PatchDlg.DeskewCB.Checked := ScanDeskew;
+ PatchDlg.ImgSetUseCB.Checked := ScanImgSetUse;
+ PatchDlg.SpinEdit1.Value := ScanBright;
+ PatchDlg.SpinEdit2.Value := ScanContrast;
+ case ScanRotate of
+ 0 : PatchDlg.ScanRotateRG.ItemIndex := 0;
+ 270 : PatchDlg.ScanRotateRG.ItemIndex := 1;
+ 180 : PatchDlg.ScanRotateRG.ItemIndex := 2;
+ 90 : PatchDlg.ScanRotateRG.ItemIndex := 3;
+ end;
+ Case ScanImgShowMode of
+ 0 : PatchDlg.ScanShowRG.ItemIndex := 0;
+ 1 : PatchDlg.ScanShowRG.ItemIndex := 1;
+ 2 : PatchDlg.ScanShowRG.ItemIndex := 2;
+ end;
+ If PatchDlg.ShowModal = mrOk then
+ begin
+ DeviceDelete := PatchDlg.BlankuseCB.Checked;
+ DeviceDeleteSize := PatchDlg.SpinEdit5.Value;
+ ScanDpi := Strtoint(PatchDlg.ComboBox1.Text);
+ ScannerReverse := PatchDlg.ReverseCB.Checked;
+ BoardClear := PatchDlg.BorderCB.Checked;
+ ScanDeskew := PatchDlg.DeskewCB.Checked;
+ ScanDuplex := PatchDlg.DuplexCB.Checked;
+ ScanImgSetUse := PatchDlg.ImgSetUseCB.Checked;
+ ScanBright := PatchDlg.SpinEdit1.Value;
+ ScanContrast := PatchDlg.SpinEdit2.Value;
+ Case PatchDlg.ScanRotateRG.ItemIndex of
+ 0:ScanRotate := 0;
+ 1:ScanRotate := 270;
+ 2:ScanRotate := 180;
+ 3:ScanRotate := 90;
+ end;
+ Case PatchDlg.ScanShowRG.ItemIndex of
+ 0:ScanImgShowMode := 0;
+ 1:ScanImgShowMode := 1;
+ 2:ScanImgShowMode := 2;
+ end;
+ R_W_ScanIni('W');
+ ScanDuplexCB.Checked := ScanDuplex;
+ end;
+ finally
+ PatchDlg.Free;
+ DataLoading(False,False);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PageLVClick(Sender: TObject);
+begin
+ IF PageLV.Selected = nil Then Exit;
+ PageLVclear := False;
+ ScrollBar1.Position := PageLV.Selected.Index+1;
+ PageLVclear := True;
+end;
+
+procedure TCB_IMGPSScanX.PageLVKeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ IF PageLV.Selected = nil Then Exit;
+ ScrollBar1.Position := PageLV.Selected.Index+1;
+end;
+
+procedure TCB_IMGPSScanX.PageLVMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ IF Button = TMouseButton(MbRight) Then
+ begin
+ If PageLV.GetItemAt(X,Y) = nil then Exit;
+ PageLV.Selected := PageLV.GetItemAt(X,Y);
+ PageLVClick(self);
+ PageLV.PopupMenu.Popup(Mouse.CursorPos.X ,Mouse.CursorPos.Y);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.Panel11DblClick(Sender: TObject);
+begin
+ // Button3.Visible := not Button3.Visible;
+ //Button4.Visible := not Button4.Visible;
+ //self.FCustDocYN := 'N';
+end;
+
+procedure TCB_IMGPSScanX.Panel1DblClick(Sender: TObject);
+begin
+ Button1.Visible := not Button1.Visible;
+ Button2.Visible := not Button2.Visible;
+end;
+
+procedure TCB_IMGPSScanX.Panel9Resize(Sender: TObject);
+begin
+ GoViewMode;
+end;
+
+procedure TCB_IMGPSScanX.PM101Click(Sender: TObject);
+var
+ P,v,v1,v2,ln,i : Integer;
+ iDocDir,iDocNo : String;
+begin
+LogFile1.LogToFile(logTimeString+'Tree 按下刪除');
+ if TreeView1.Selected = NewTreeNode then //全刪 //新掃描件
+ begin
+LogFile1.LogToFile(logTimeString+'Tree 全部刪除');
+ If Messagedlg(_Msg('是否刪除所有案件?'),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+ clearView(1);
+ Application.ProcessMessages;
+ _DelTree(ImageSavePath);
+ if (FMode = 'ESCAN') then
+ begin
+ MkDir(ImageSavePath+FCaseID);
+ CreateEmptyCase(ImageSavePath,FCaseID);
+ end;
+ LoadImgFile;
+ Showmessage(_Msg('刪除完成'));
+ end
+ Else if TreeView1.Selected = MyTreeNode1 then //案件編號
+ begin
+LogFile1.LogToFile(logTimeString+'Tree 案件編號刪除 NowCaseno='+NowCaseno);
+ If Messagedlg(Format(_Msg('編號(%s)是否刪除?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+ clearView(1);
+ Application.ProcessMessages;
+ if (FMode = 'ESCAN') then
+ begin
+ for i := 0 to MyTreeNode1.Count - 1 do
+ begin
+ MyTreenode2 := MyTreeNode1.Item[i];
+ v := Posend('{',MyTreenode2.Text);
+ v1 := Posend('}',MyTreenode2.Text);
+ v2 := posend('-',MyTreenode2.Text);
+ ln := length(MyTreenode2.Text);
+ iDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
+ iDocNo := DocNoDir2DocNo(iDocDir);
+ _DelTree(ImageSavePath+NowCaseno+'\'+iDocDir);
+ SetUseCase('D',ImageSavePath+NowCaseno+'\',iDocDir,'','');
+ SetDocNoList('D',-1,NowCaseNo,iDocDir,'');
+ if (Copy(iDocNo,1,5)='ZZZZZ') then //20140703 刪除自定文件時要刪ini檔資料
+ DeleteCustomDocDir(ImageSavePath+NowCaseno+'\',iDocDir);
+
+ end
+ end
+ Else
+ begin
+ _DelTree(DisplayPath);
+ SetCaseList('D',NewTreeNode.IndexOf(MyTreeNode1),'');
+ end;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+
+ if (FMode = 'ESCAN') then
+ begin
+ if not DirectoryExists(ImageSavePath+FCaseID) then
+ begin
+ MkDir(ImageSavePath+FCaseID);
+ CreateEmptyCase(ImageSavePath,FCaseID);
+ end;
+ end;
+ LoadImgFile;
+ end
+ Else if TreeView1.Selected = MyTreeNode2 then //文件層
+ begin
+ If Messagedlg(Format(_Msg('文件(%s)是否刪除?'),[DocNo2DocName(NowCaseno,NowDocNo)]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+ ClearView(1);
+ Application.ProcessMessages;
+//ShowMessage(NowDocDir);
+LogFile1.LogToFile(logTimeString+'Tree 文件層號刪除 NowDocDir='+NowDocDir);
+ if (Length(NowDocDir)=8) or (NowDocDir=AttName) then
+ begin
+//ShowMessage('DeleteDocNoFileForESCAN');
+ DeleteDocNoFileForESCAN(ImageSavePath+NowCaseno+'\'+NowDocDir,NowDocDir);
+ end
+ else
+ begin
+ _DelTree(ImageSavePath+NowCaseno+'\'+NowDocDir);
+ SetDocNoList('D',-1,NowCaseNo,NowDocDir,'');
+ end;
+ SetUseCase('D',ImageSavePath+NowCaseno+'\',NowDocDir,'','');
+
+ if (Copy(NowDocNo,1,5)='ZZZZZ') then //20140703 刪除自定文件時要刪ini檔資料
+ DeleteCustomDocDir(ImageSavePath+NowCaseno+'\',NowDocDir);
+
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ NewTreeNodeRefresh;
+
+ end
+ Else if TreeView1.Selected = MyTreeNode3 then //FormID層
+ begin
+ If Messagedlg(Format(_Msg('文件(%s)是否刪除?'),[NowFormName]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+LogFile1.LogToFile(logTimeString+'Tree FormID層號刪除 NowFormCode='+NowFormCode);
+ DeleteFormCodeFile(NowCaseNo,NowDocDir,NowFormCode);
+ SetRecordEditedDocDir('A',NowCaseNo,NowDocDir);
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ NewTreeNodeRefresh;
+
+ end;
+end;
+
+procedure TCB_IMGPSScanX._DelTreeForExistImg(ASourceDir:String);
+var
+ i:integer;
+ ST:TStringList;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.PM102Click(Sender: TObject);
+var
+ NewCaseID,ShowNewCaseID,ShowNowCaseID : String;
+ i,P,v : Integer;
+ InputOk : Boolean;
+begin
+ VMode := 0;
+ GoViewMode;
+ ISB1.ZoomMode := zmFitWidth;
+
+ NewCaseID := InputBox(_Msg('修改案件編號'),_Msg('新案件編號'),'');
+ ShowNewCaseID := NewCaseID;
+ ShowNowCaseID := NowCaseno;
+
+ if NewCaseID = '' then Exit;
+
+ IF Length(NewCaseID)<>CaseIDLength Then
+ begin
+ Showmessage(_Msg('輸入格式錯誤'));
+ Exit;
+ end;
+
+ if DirectoryExists(ImageSavePath+NewCaseID) then
+ begin
+ Showmessage(NewCaseID+_Msg('己存在,無法修改'));
+ Exit;
+ end;
+
+ if Messagedlg(Format(_Msg('是否將%s改為%s'),[ShowNowCaseID,ShowNewCaseID]),Mtconfirmation,[mbyes,mbcancel],0) = mrcancel then
+ Exit;
+ ClearView(1);
+ RenameFile(ImageSavePath+NowCaseno,ImageSavePath+NewCaseID);
+ SetCaseList('E',NewTreeNode.IndexOf(MyTreeNode1),NewCaseID);
+
+ //P := ContextList.Count;
+ MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NewCaseID,GetCasePage(ImageSavePath,NewCaseID)]);
+ //DrawDocItem(MyTreeNode1,FORM_INF_List,NewCaseID);
+ DrawDocItem2(MytreeNode1,NewCaseID);
+ Showmessage(_Msg('修改完成'));
+end;
+
+procedure TCB_IMGPSScanX.PM103Click(Sender: TObject);
+begin
+ if TreeView1.Selected = nil then Exit;
+
+ {if Treeview1.Selected = NewTreeNode then
+ begin
+ ShowMessage('AAAAA');
+ end;
+ if Treeview1.Selected = MyTreeNode1 then
+ begin
+ ShowMessage('BBBBB');
+ end;
+
+ if Treeview1.Selected = MyTreeNode2 then
+ begin
+ ShowMessage('CCCCC');
+ end;
+
+ if Treeview1.Selected = MyTreeNode3 then
+ begin
+ ShowMessage('DDDDD');
+ end;
+ }
+ if (Treeview1.Selected = NewTreeNode) {or (Treeview1.Selected = MyTreeNode1)} then
+ begin
+//ShowMessage('NewScanBtnClick');
+LogFile1.LogToFile(logTimeString+'Tree NewScanBtnClick');
+ NewScanBtnClick(self)
+ end
+ Else
+ begin
+//ShowMessage('AddScanBtnclick');
+LogFile1.LogToFile(logTimeString+'Tree AddScanBtnclick');
+ AddScanBtnclick(self);
+ end;
+end;
+
+
+Procedure TCB_IMGPSScanX.PM104Click(Sender: TObject);
+Var
+ i, n, m, ii, P, v, v1, page, imageCount: Integer;
+ FName: String;
+ CaseID, DocNo, FormID: String;
+ DocDir: String;
+ SavePath, SaveFilename: String;
+ ISB: TImageScrollBox;
+ FileRec: TSearchrec;
+
+ iGraphic, iGraphic_First, iGraphic_sec: TTiffGraphic;
+ iRect : TRect;
+ JpgGr : TJpegGraphic;
+ SaveStream : TFileStream;
+ SaveStreamA:TFileStream;
+ SaveStreamB:TFileStream;
+ cooom:integer;
+Begin
+ OpenDialog1.Filter := 'Image files|*.TIF;*.JPG;*.PNG';
+ If OpenDialog1.Execute Then
+ Begin
+ ISB := TImageScrollBox.Create(self);
+try
+ ShowText := _Msg('檔案加入中,請稍候');
+LogFile1.LogToFile(logTimeString+'檔案加入中開始');
+ DataLoading(True, True);
+ If TreeView1.Selected = Nil Then
+ Exit;
+ FName := OpenDialog1.FileName;
+
+ FindFirst(FName, faAnyfile, FileRec);
+
+ If FFileSizeLimit = 0 Then
+ Begin
+ FFileSizeLimit := 5 * 1024;
+ End;
+//FFileSizeLimit:=20*5*1024;
+//ShowMessage(IntToStr(FileRec.Size)+','+IntToStr(FFileSizeLimit * 1024));
+ If FileRec.Size > FFileSizeLimit * 1024 Then // 檢查檔案大小
+ Begin
+ ShowMessage(Format(_Msg('目前檔案大小為 %.3f MB,已超過單一檔案匯入限制%1.f MB'),[FileRec.Size / (1024*1024),FFileSizeLimit/1024]));
+ {ShowMessage(Format('目前檔案大小為 %.3f MB', [FileRec.Size / (1024*1024)]) +
+ ',已超過單一檔案匯入限制'+Format('%.1f',[FFileSizeLimit/1024])+'MB');}
+ FindClose(FileRec);
+ DataLoading(false, false);
+ Exit;
+ End;
+ //MessageDlg()
+ //cooom:=StrToInt(InputBox('輸入百分比','輸入百分比',''));
+ cooom:=FJpgCompression;//20171211彩色tif採jpg壓縮的比例
+
+ FindClose(FileRec);
+ CaseID := NowCaseno;
+ imageCount := 0;
+ P := ISB.ImageCountFromFile(OpenDialog1.FileName);
+ For i := 1 To P Do
+ Begin
+ ShowText := Format(_Msg('檔案加入中,請稍候(%d/%d)'),[i,p]);
+ //ShowText := _Msg('檔案加入中,請稍候')+'(' + inttostr(i) + '/' + inttostr(P) + ')';
+ DataLoading(True, True);
+ ISB.LoadFromFile(FName, i);
+ DeskewImg(ISB.Graphic);
+
+
+ ISB_BW.Graphic.Assign(ISB.Graphic); //20180104
+ If ISB.Graphic.ImageFormat <> ifBlackWhite Then //20180104
+ begin
+ ConvertToBW(ISB_BW.Graphic);
+ end;
+ ///ISB_BW.SaveToFile('KKKKKKKK.tif');
+
+ iGraphic_First := TTiffGraphic.Create;
+ iGraphic_sec := TTiffGraphic.Create;
+
+
+ //ShowMessage(IntToStr(iGraphic_First.Palette.palNumEntries)); //彩色 會為0 黑白 為2
+
+ MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf); //判斷A3 有用FormID 所以要先辨條碼
+ For n := 1 To MpsBarcodeinf.Count Do
+ Begin
+ If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
+ Begin
+ Rotate(ISB.Graphic, MpsBarcodeinf.r180[n]);
+ //MpsGetBarcode(iGraphic_First, MpsBarcodeinf);
+ Break;
+ End;
+ End;
+
+ iGraphic_First.Assign(ISB.Graphic);
+ //有必要的話先把影像轉正 再開始切圖
+ If CheckNeedCrop(iGraphic_First) Then
+ Begin
+ // 先取右邊的影像
+ iRect.Left := ISB.Graphic.Width Div 2;
+ iRect.Right := ISB.Graphic.Width;
+ iRect.Top := 0;
+ iRect.Bottom := ISB.Graphic.Height;
+ CropImg(iGraphic_First, iRect);
+
+ iGraphic_sec.Assign(ISB.Graphic);
+ // 再取左邊的影像
+ iRect.Left := 0;
+ iRect.Right := ISB.Graphic.Width Div 2;
+ iRect.Top := 0;
+ iRect.Bottom := ISB.Graphic.Height;
+ CropImg(iGraphic_sec, iRect);
+ End;
+ ISB.Graphic.Clear; //20220711 Hong 覺得ISB後面沒有到了,先清掉減少記憶體使用
+ iGraphic := iGraphic_First;
+
+ While Not iGraphic.IsEmpty Do
+ Begin
+ If (TreeView1.Selected = NewTreeNode) Or
+ (TreeView1.Selected = MyTreeNode1) Then
+ Begin
+ SaveFilename := '';
+ ISB_BW.Graphic.Assign(iGraphic); //20180104
+ If iGraphic.ImageFormat <> ifBlackWhite Then //20180104
+ begin
+ ConvertToBW(ISB_BW.Graphic);
+ end;
+ MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
+//ShowMessage(IntToStr(MpsBarcodeinf.Count));
+ For n := 1 To MpsBarcodeinf.Count Do
+ Begin
+ If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
+ Begin
+ Rotate(iGraphic, MpsBarcodeinf.r180[n]);
+ MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
+ Break;
+ End;
+ End;
+//ShowMessage('XXX '+IntToStr(MpsBarcodeinf.Count));
+ FormID := BarCode2FormID;
+//ShowMessage('FormID='+FormID);
+ // 取出FormID
+ SaveFilename := FormID;
+ If (TreeView1.Selected = NewTreeNode) Then
+ Begin
+ If FindDivFormCode(FormID) Then // 只找分案頁上的案件條碼
+ Begin
+ imageCount := 0;
+ ClearView(1);
+ ContextList.Clear;
+ CaseID := BarCode2CaseID;
+ If DirectoryExists(ImageSavePath + CaseID + '\') Then
+ Begin
+ _DelTree(ImageSavePath + CaseID + '\');
+ SetCaseList('D', -1, CaseID);
+ End;
+ End;
+ If CaseID = '' Then
+ Begin
+ CaseID := GetNoNameCase(ImageSavePath);
+ ContextList.Clear;
+ End;
+ End;
+ SavePath := ImageSavePath + CaseID + '\';
+ Str2Dir(SavePath);
+
+ DocNo := FormCode2DocNo(FormID);
+ DocDir := FindLastestDocDir(CaseID, DocNo);
+ if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) then
+ begin
+ DocDir := FindLastestDocDirForPage(CaseID, DocNo,FormID);
+//ShowMessage('DocDir='+DocDir);
+ end;
+
+ If DocNoNeedDiv(DocNo) Then // 要分份數
+ Begin
+ If ((FormCode2Page(FormID) = '01') And
+ (GetDocDir_Page(CaseID, DocDir) > 0)) Or (DocDir = '') Then
+ begin
+ DocDir := DocNo2DocNoDir(ImageSavePath + CaseID + '\', DocNo);
+ end;
+ End
+ Else // 不分份數
+ Begin
+ If DocNo <> '' Then
+ DocDir := DocNo
+ Else // Attach 附件
+ DocDir := DocNo2DocNoDir(ImageSavePath + CaseID + '\', DocNo);
+ End;
+
+ If (Not DirectoryExists(ImageSavePath + CaseID + '\' + DocDir + '\'))
+ And (DocDir <> AttName) Then
+ SetDocNoList('A', -1, CaseID, DocDir, '1');
+ SavePath := ImageSavePath + CaseID + '\' + DocDir + '\';
+ Str2Dir(SavePath);
+ ContextList.Clear;
+ If FileExists(SavePath + 'Context.dat') Then
+ ContextList.LoadFromFile(SavePath + 'Context.dat');
+
+ WriteCaseIndex(ImageSavePath + CaseID + '\');
+ // 寫入案件索引
+ If SaveFilename = '' Then // 附件
+ SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + ext
+ Else
+ SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + '_' +
+ SaveFilename + ext;
+
+ For n := 1 To MpsBarcodeinf.Count Do
+ Begin
+ If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
+ Begin
+ Rotate(iGraphic, MpsBarcodeinf.r180[n]);
+ MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
+ Break;
+ End;
+ End;
+//ShowMessage(IntToStr(iGraphic.Palette.palNumEntries));
+ if iGraphic.ImageFormat = ifBlackWhite then //20200806 出現無法匯入,是因color256無法壓JPEG,待報會後再開啟
+ begin
+ SaveFilename := changefileext(SaveFilename,'.tif'); //20240320 Hong 調整黑白存tif
+ iGraphic.Compression:=tcGroup4;
+ end
+ else if iGraphic.ImageFormat= ifColor256 then
+ begin
+ SaveFilename := changefileext(SaveFilename,'.jpg'); //20240320 Hong 調整Color256存jpg
+ ConverttoGray(iGraphic);
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=cooom;
+ end
+ else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then
+ begin
+ SaveFilename := changefileext(SaveFilename,'.jpg'); //20240320 Hong 調整彩色灰階存jpg
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=cooom;
+ end
+ else
+ begin
+ iGraphic.Compression:=tcLZW;
+ end;
+
+ {if (iGraphic.Palette.palNumEntries = 0) or (iGraphic.Palette.palNumEntries = 256) then //20171130 彩色 會為0 黑白 為2 灰階256 //20200806拿掉
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=cooom;
+ end;}
+
+ If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.tif' Then
+ Begin
+ If FileExists(SavePath + SaveFilename) Then
+ SaveStream := TFileStream.Create(SavePath + SaveFilename, fmOpenReadWrite)
+ Else
+ SaveStream := TFileStream.Create(SavePath + SaveFilename, fmCreate);
+ Try
+ SaveStream.Seek(0, soFromBeginning);
+ iGraphic.AppendToStream(SaveStream);
+ Finally
+ SaveStream.Free;
+ End;
+ End
+ Else If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.jpg' Then
+ Begin
+ If FileExists(SavePath + SaveFilename) Then
+ DeleteFile(SavePath + SaveFilename);
+ // SaveStream := TFileStream.Create( PEFileName ,fmCreate );
+ JpgGr := TJpegGraphic.Create;
+ Try
+ JpgGr.Assign(iGraphic);
+ JpgGr.SaveQuality := 30;
+ // JpgGr.AppendToStream(SaveStream);
+ JpgGr.SaveToFile(SavePath + SaveFilename);
+ Finally
+ JpgGr.Free;
+ // SaveStream.Free;
+ End;
+ End;
+
+ SetContextList('A', -1, CaseID, DocDir, SaveFilename);
+ If (TreeView1.Selected = NewTreeNode) Then
+ Begin
+ If imageCount = 0 Then
+ Begin
+ SetCaseList('A', -1, CaseID);
+ MyTreeNode1 := TreeView1.Items.AddChild(NewTreeNode, CaseID);
+ MyTreeNode1.ImageIndex := 2;
+ MyTreeNode1.SelectedIndex := 2;
+ Application.ProcessMessages;
+ End;
+ End;
+ inc(imageCount);
+ // DrawDocItem1(MytreeNode1,Doc_Inf_List,CaseID);
+ // DrawDocItem(MyTreeNode1,FORM_INF_List,CaseID);
+ End
+ Else If TreeView1.Selected = MyTreeNode3 Then
+ Begin
+ SavePath := ImageSavePath + CaseID + '\' + NowDocDir + '\';
+ ContextList.Clear;
+ If FileExists(ImageSavePath + CaseID + '\' + NowDocDir +
+ '\Context.dat') Then
+ ContextList.LoadFromFile(ImageSavePath + CaseID + '\' + NowDocDir +
+ '\Context.dat');
+ If NowFormCode <> '' Then
+ SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + '_' +
+ NowFormCode + ext
+ Else
+ SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + ext;
+
+ For n := 1 To MpsBarcodeinf.Count Do
+ Begin
+ If MpsBarcodeinf.r180[n] <> 0 Then // 依條碼角度轉影像
+ Begin
+ Rotate(iGraphic, MpsBarcodeinf.r180[n]);
+ MpsGetBarcode(iGraphic, MpsBarcodeinf);
+ Break;
+ End;
+ End;
+
+ if (iGraphic.Palette.palNumEntries = 0) or (iGraphic.Palette.palNumEntries = 256) then //20171130 彩色 會為0 黑白 為2
+ begin
+ iGraphic.Compression:=tcJPEG;
+ iGraphic.JpegQuality:=cooom;
+ end;
+
+ If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.tif' Then
+ Begin
+ If FileExists(SavePath + SaveFilename) Then
+ SaveStream := TFileStream.Create(SavePath + SaveFilename,
+ fmOpenReadWrite)
+ Else
+ SaveStream := TFileStream.Create(SavePath + SaveFilename,
+ fmCreate);
+ Try
+ SaveStream.Seek(0, soFromBeginning);
+ iGraphic.AppendToStream(SaveStream);
+ Finally
+ SaveStream.Free;
+ End;
+ End
+
+ Else
+ Begin
+ If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.jpg' Then
+ Begin
+ If FileExists(SavePath + SaveFilename) Then
+ DeleteFile(SavePath + SaveFilename);
+ // SaveStream := TFileStream.Create( PEFileName ,fmCreate );
+ JpgGr := TJpegGraphic.Create;
+ Try
+ JpgGr.Assign(iGraphic);
+ JpgGr.SaveQuality := cooom;
+ // JpgGr.AppendToStream(SaveStream);
+ JpgGr.SaveToFile(SavePath + SaveFilename);
+ Finally
+ JpgGr.Free;
+ // SaveStream.Free;
+ End;
+ End;
+
+ End;
+ // ISB.SaveToFile(SavePath+SaveFilename);
+ ContextList.Add(SaveFilename);
+ ContextList.SaveToFile(SavePath + 'Context.dat');
+ End;
+
+ if iGraphic = iGraphic_First then
+ iGraphic := iGraphic_Sec
+ else
+ iGraphic.Assign(nil);
+
+ End //While 結束
+
+ End;
+ ClearErrini(CaseID, MyTreeNode1);
+ // 清掉檢核記錄
+ If (TreeView1.Selected = MyTreeNode1) Or
+ (TreeView1.Selected = NewTreeNode) Then
+ Begin
+ LoadImgFile;
+ End
+ Else
+ Begin
+ DrawDocItem2(MyTreeNode1, CaseID);
+ // 長出文件名稱的樹並傳回是否有申請書的影像
+ page := GetCasePage(ImageSavePath, CaseID);
+ // ShowMessage('page='+IntToStr(page));
+ MyTreeNode1.Text := Format(_Msg('%s-%d頁'), [CaseID, page]);
+ End;
+ // ShowMessage('AAAA');
+ NewTreeNodeRefresh;
+ Application.ProcessMessages;
+ DataLoading(false, false);
+
+
+finally
+ISB.Free;
+iGraphic_First.Free;
+iGraphic_sec.Free;
+end;
+
+
+ End;
+End;
+
+
+
+procedure TCB_IMGPSScanX.PM106Click(Sender: TObject);
+var
+ i,n,x,v,v1 : Integer;
+ CopyFormID,Copy2Caseno,CopyFileName : String;
+ S : TStringlist;
+begin
+ ShowText := _Msg('複製文件中,請稍候');
+ DataLoading(True,True);
+ DocCopyForm := TDocCopyForm.Create(Self);
+ S := TStringlist.Create;
+ try
+ InitialLanguage(DocCopyForm); //載入多國語言
+ DocCopyForm.CopyFromGB.Caption := NowCaseno+DocCopyForm.CopyFromGB.Caption;
+ IF NewTreenode.Count = 1 Then
+ begin
+ Showmessage(_Msg('沒有其他可複製的文件'));
+ Exit;
+ end;
+ For i := 0 to MyTreeNode1.Count -1 do
+ begin
+ v := Pos('-',MyTreeNode1.Item[i].Text);
+ v1 := pos('{',MyTreeNode1.Item[i].Text);
+ if V1 > 0 then
+ begin
+ CopyFormID := Copy(MyTreeNode1.Item[i].Text,1,v-1);
+ DocCopyForm.CheckListBox1.Items.Add(CopyFormID);
+ end;
+ end;
+ For i := 0 to NewTreenode.Count -1 do
+ begin
+ v := Posend('-',NewTreeNode.Item[i].Text);
+ Copy2Caseno := Copy(NewTreeNode.Item[i].Text,1,v-1);
+ IF Copy2Caseno <> NowCaseno Then
+ begin
+ DocCopyForm.CheckListBox2.Items.Add(Copy2Caseno);
+ end;
+ end;
+
+ if DocCopyForm.ShowModal = mrok then
+ begin
+ If MessageDlg(_Msg('是否確定要將勾選的文件複製到勾選的編號裡?'),MtConfirmation,[Mbyes,mbcancel],0) = mrCancel Then
+ Exit;
+ ShowText := _Msg('複製中,請稍候');
+ DataLoading(True,True);
+ For i := 0 to DocCopyForm.CheckListBox2.Count -1 do
+ begin
+ IF DocCopyForm.CheckListBox2.Checked[i] Then
+ begin
+ S.Clear;
+ Copy2Caseno := DocCopyForm.CheckListBox2.Items.Strings[i];
+ ClearErrini(Copy2Caseno,MyTreeNode1); //清掉檢核記錄
+ S.LoadFromFile(ImageSavePath + Copy2Caseno +'\Context.dat');
+ For n := 0 to DocCopyForm.CheckListBox1.Count -1 do //文件
+ begin
+ If DocCopyForm.CheckListBox1.Checked[n] Then
+ begin
+ //v:= Posend('{',DocCopyForm.CheckContextList.Strings[n]);
+ //v1 := Posend('}',DocCopyForm.CheckContextList.Strings[n]);
+ //CopyFormID := Copy(DocCopyForm.CheckContextList.Strings[n],1,v-1);
+ CopyFormID := DocCopyForm.CheckListBox1.Items.Strings[n];
+ IF v = 0 Then
+ CopyFormID := '';
+ For x := 0 to ContextList.Count -1 do
+ begin
+ //Showmessage(CopyFormCode);
+ //IF CopyFormID <> '' then //有文件代號
+ // begin
+ if FileName2FormCode(ContextList.Strings[x])=CopyFormID then
+ begin
+ //CopyFileName := Add_Zoo(S.Count+1,3)+ Copy(ContextList.Strings[x],4,length(ContextList.Strings[x])-3);
+ CopyFileName := Add_Zoo(S.Count+1,3)+ FileName2NoQuene_Filename(ContextList.Strings[x]);
+ CopyFile(PWideChar(DisplayPath+ContextList.Strings[x]),PWidechar(ImageSavePath + Copy2Caseno+'\'+CopyFileName),False);
+ S.Add(CopyFileName);
+ S.SaveToFile(ImageSavePath + Copy2Caseno +'\Context.dat');
+ end;
+ // end
+
+ end;
+ end;
+ end;
+
+ end;
+ end;
+ DataLoading(False,False);
+ Showmessage(_Msg('複製完成!!'));
+ LoadImgFile;
+ end;
+ finally
+ DocCopyForm.Free;
+ DataLoading(False,False);
+ S.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PM107Click(Sender: TObject);
+begin
+ WNoteBtnClick(nil);
+end;
+
+procedure TCB_IMGPSScanX.PM108Click(Sender: TObject);
+var
+ i : Integer;
+ DocListForm : TDocListForm;
+ OldName,NewName,Ext : String;
+ NewFormID,NewFormName,CustomDocNo : String;
+begin
+ DocListForm := TDocListForm.Create(self);
+ try
+LogFile1.LogToFile(logTimeString+'Tree 歸類開始');
+ InitialLanguage(DocListForm); //載入多國語言
+ DocListForm.CheckBox1.Visible:=True;
+ for i := 1 to FORM_INF_List.Count - 1 do
+ begin
+ NewFormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ NewFormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
+ if not FormIDAppear(NewFormID) then Continue; //20170816 先秀全部的
+ if (NewFormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(NewFormID,False,i) then
+ begin
+ DocListForm.FormIDList.Add(NewFormID+'#@#'+NewFormName);
+ With DocListForm.DocLV.Items.Add do
+ begin
+ Caption := NewFormID;
+ SubItems.Add(GetSQLData(FORM_INF_List,'T1.FORM_DESC',i));
+ end;
+ end;
+ end;
+ if DocListForm.ShowModal = mrOk then
+ begin
+ if not (DocListForm.DocLV.Selected=nil) then
+ NewFormID := DocListForm.DocLV.Selected.Caption;
+ if DocListForm.CheckBox1.Checked then
+ begin
+ //歸類到自訂文件
+ NewFormID:=DocListForm.Edit1.Text;
+
+ if Trim(DocListForm.Edit1.Text)='' then
+ begin
+ Showmessage(_Msg('未輸入文件名稱'));
+ Exit;
+ end;
+ if FindCustomDocName(DisplayPath,NewFormID) then
+ begin
+ Showmessage(Format(_Msg('文件名稱:"%s"己存在'),[NewFormID]));
+ Exit;
+ end;
+ if NowFormCode <> AttName then
+ begin
+ If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[FormCode2FormName(NowCaseNo,NowFormCode),NewFormID]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
+ Exit;
+ end
+ Else
+ begin
+ If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[_Msg('附件')+MyTreeNode3.Text,FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
+ Exit;
+ end;
+ CustomDocNo := GetNewCustomDocNo(DisplayPath,NewFormID);
+//ShowMessage('CustomDocNo='+CustomDocNo);
+LogFile1.LogToFile(logTimeString+'Tree 歸類到自訂文件 CustomDocNo='+CustomDocNo);
+ ShowText := _Msg('歸類中,請稍侯');
+ DataLoading(True,True);
+ FormIDReplace(NowCaseNo,NowDocDir,NowFormCode,CustomDocNo+'010101A');
+ end
+ else
+ begin
+ //歸類到既有文件
+ if NowFormCode <> AttName then
+ begin
+ If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[FormCode2FormName(NowCaseNo,NowFormCode),FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
+ Exit;
+ end
+ Else
+ begin
+ If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[_Msg('附件')+MyTreeNode3.Text,FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
+ Exit;
+ end;
+ ShowText := _Msg('歸類中,請稍侯');
+ DataLoading(True,True);
+//ShowMessage('NowDocDir='+NowDocDir);
+LogFile1.LogToFile(logTimeString+'Tree 歸類到既有文件 NewFormID='+NewFormID);
+ FormIDReplace(NowCaseNo,NowDocDir,NowFormCode,NewFormID);
+
+ end;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ DataLoading(False,False);
+ TreeView1.Selected := MyTreeNode1;
+ TreeView1Click(self);
+ end;
+
+ finally
+ DocListForm.Free;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.PM109Click(Sender: TObject);
+var
+ S : TStringlist;
+ CaseID : String;
+begin
+ //if TreeView1.Selected = nil then Exit;
+ //if TreeView1.Selected = NewTreeNode then Exit;
+ CaseID := NowCaseno;
+ S := TStringlist.Create;
+ try
+ ClearView(1);
+ ShowText := CaseID+_Msg('檢核中,請稍候');
+ DataLoading(True,True);
+ ShowText := CaseID+_Msg('檢核中,請稍候');
+ DataLoading(True,True);
+ If OMRCheckCase(CaseID) then //有成功
+ begin
+ S.Add('Y');
+ S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
+ end;
+ //MyTreeNode2ReFresh(CaseID);
+ LoadImgFile;
+ TreeView1Click(nil);
+ DataLoading(False,False);
+ finally
+ S.Free;
+ end;
+ Showmessage(_Msg('檢核完成'));
+end;
+
+procedure TCB_IMGPSScanX.PM110Click(Sender: TObject);
+var
+ CustomDocName : String;
+ CustomDocNo : String;
+ DocDir : String;
+ SavePath : String;
+ ST1:TStringList;
+begin
+ if InputQuery(_Msg('輸入其他文件名稱'),_Msg('文件名稱'),CustomDocName) then
+ begin
+ if CustomDocName <> '' then
+ begin
+ if FindCustomDocName(DisplayPath,CustomDocName) then
+ begin
+ Showmessage(Format('文件名稱:"%s"己存在',[CustomDocName]));
+ Exit;
+ end;
+ ST1:=TStringList.Create;
+ CustomDocNo := GetNewCustomDocNo(DisplayPath,CustomDocName);
+ DocDir := CustomDocNo;
+ SavePath := ImageSavePath+NowCaseNo+'\'+DocDir+'\';
+ Str2Dir(SavePath);
+ SetDocNoList('A',-1,NowCaseNo,DocDir,'1');
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ MyTreeNode1.Expand(True);
+ end;
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.PM111Click(Sender: TObject);
+var
+ oldCopies,NewCopies : Integer;
+ copies : String;
+begin
+ oldCopies := GetDocDirCopies(NowCaseno,NowDocDir);
+ try
+ NewCopies := Strtoint(inputBox(_Msg('修改份數'),_Msg('請輸入修改後的份數'),inttostr(oldCopies)));
+ except
+ Showmessage(_Msg('輸入錯誤'));
+ Exit;
+ end;
+ if (NewCopies <= 0) and (NewCopies >= 10000) then
+ begin
+ Showmessage(_Msg('輸入範圍錯誤'));
+ Exit;
+ end;
+
+ if (oldCopies <> NewCopies) and (NewCopies > 0) and (NewCopies < 10000) then
+ begin
+ if DocNoNeedDiv(NowDocNo) and (NewCopies = 1) and (MessageDlg(_Msg('修改至1份後此文件將無法再進行份數修改,是否確定??'),mtConfirmation,[mbyes,mbcancel],0)= mrcancel) then
+ Exit;
+
+ SetDocDirCopies(NowCaseno,NowDocDir,NewCopies);
+ SetRecordEditedDocDir('A',NowCaseNo,NowDocDir);
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ Showmessage(_Msg('修改完成'));
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.PM301Click(Sender: TObject);
+begin
+ ScanColor := ifBlackWhite;
+ ScanDpi := Def_ScanDpi;
+ Ext := '.tif';
+ PM301.Checked := True;
+end;
+
+procedure TCB_IMGPSScanX.PM302Click(Sender: TObject);
+begin
+ ScanColor := ifGray256;
+ Ext := '.jpg';
+ ScanDpi := 200;
+ //Ext := '.tif';
+ PM302.Checked := True;
+end;
+
+procedure TCB_IMGPSScanX.PM303Click(Sender: TObject);
+begin
+ ScanColor := ifTrueColor;
+ Ext := '.jpg'; //20130326 yuu說理賠改存jpg
+ ScanDpi := 200;
+ //Ext := '.tif';
+ PM303.Checked := True;
+end;
+
+procedure TCB_IMGPSScanX.PM501Click(Sender: TObject);
+begin
+ DisplayISB.ZoomMode := zmFitWidth;
+ DisplayISB.AntiAliased := True;
+ SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
+end;
+
+procedure TCB_IMGPSScanX.PM502Click(Sender: TObject);
+begin
+ DisplayISB.ZoomMode := zmFitHeight;
+ DisplayISB.AntiAliased := True;
+ SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
+end;
+
+procedure TCB_IMGPSScanX.PM503Click(Sender: TObject);
+begin
+ DisplayISB.ZoomMode := zmFittoPage;
+ DisplayISB.AntiAliased := True;
+ SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
+end;
+
+procedure TCB_IMGPSScanX.PM504Click(Sender: TObject);
+begin
+ DisplayISB.ZoomMode := zmOriginalSize;
+ DisplayISB.AntiAliased := True;
+ SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
+end;
+
+procedure TCB_IMGPSScanX.PM505Click(Sender: TObject);
+begin
+ if DisplayISB.FileName = '' then Exit;
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ ScanMode := smReplace;
+ ScanInfo.ImageCount := 0;
+ ScanPath := DisplayPath;
+ ScanCaseno := '';
+ ScanSaveFilename := ExtractFileName(DisplayISB.FileName);
+ Try
+ StatrTwainScan;
+ Except
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ end;
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+end;
+
+procedure TCB_IMGPSScanX.PM507Click(Sender: TObject);
+var
+ i : Integer;
+ DocListForm : TDocListForm;
+ OldName,NewName,Ext : String;
+ FormID,FormName,DocNo : String;
+ PreNode2Name : String;
+ iFormID : String;
+begin
+ PreNode2Name := '';
+ if TreeView1.Selected.Parent = MyTreeNode1 then
+ PreNode2Name:= GetNode2Name(MyTreeNode2);
+ ShowText := _Msg('文件歸類中,請稍候');
+ DataLoading(True,True);
+ DocListForm := TDocListForm.Create(self);
+ try
+ InitialLanguage(PatchDlg); //載入多國語言
+ for i := 1 to FORM_INF_List.Count - 1 do
+ begin
+ FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
+ FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
+ DocNo := GetSQLData(FORM_INF_List,'T1.DOC_NO',i)+GetSQLData(FORM_INF_List,'T1.DOC_VERSION',i);
+ //Showmessage(FORM_INF_List.Text);
+ //showmessage(inttostr(FORM_INF_List.Count)+#13+inttostr(self.Doc_Inf_List.Count));
+ if (FormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(FormID,False,i) then
+ begin
+ DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
+ With DocListForm.DocLV.Items.Add do
+ begin
+ Caption := FormID;
+ SubItems.Add(FormName);
+ end;
+ end;
+ end;
+ if DocListForm.ShowModal = mrOk then
+ begin
+ OldName := ExtractFileName(DisplayISB.FileName);
+ Ext := ExtractFileExt(OldName);
+ //NewName := Copy(OldName,1,3)+'_'+TransRealFormID(DocListForm.DocLV.Selected.Caption)+Ext;
+ NewName := Add_Zoo(FileName2ScanPage(OldName),3)+'_'+DocListForm.DocLV.Selected.Caption+Ext;
+ RenameFile(DisplayPath+OldName,DisplayPath+NewName);
+ ReNameContext(DisplayPath,OldName,NewName);
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno); //201408280改
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ if PreNode2Name <> '' then // 回到原本點選的文件節點上
+ begin
+ for i := 0 to MyTreeNode1.Count - 1 do
+ begin
+ if GetNode2Name(MyTreeNode1.Item[i]) = PreNode2Name then
+ begin
+ TreeView1.Selected := MyTreeNode1.Item[i];
+ Break;
+ end;
+ end;
+ end;
+ TreeView1click(self);
+ //Showmessage(_Msg('歸類完成')); //20101103 User要求拿掉
+ end;
+ finally
+ DataLoading(False,False);
+ DocListForm.Free;
+ end;
+
+end;
+
+
+procedure TCB_IMGPSScanX.PM508Click(Sender: TObject);
+var
+ P : Integer;
+ inx:Integer;
+begin
+ if DisplayISB.FileName = '' then Exit;
+ if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'ISCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN')) then
+ begin
+ if Messagedlg(Format(_Msg('刪除後(%s)案件無影像,將刪除此案件,是否確定刪除?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
+ _DelTree(DisplayPath);
+ SetCaseList('D',NewTreeNode.IndexOf(MyTreeNode1),'');
+ LoadImgFile;
+ end
+ Else
+ begin
+ if Messagedlg(_Msg('是否確定刪除?'),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
+ inx := ContextList.IndexOf(ExtractFileName(DisplayISB.FileName));
+ ContextList.Delete(inx);
+ ContextList.SaveToFile(ImageSavePath + NowCaseno+'\Context.dat');
+ Context_DocnoList.Delete(inx);
+ Context_DocnoList.SaveToFile(ImageSavePath + NowCaseno+'\Context_DocNo.dat');
+ DeleteFile(DisplayISB.FileName);
+ ReSortFileName(DisplayPath);
+ ContextList.LoadFromFile(ImageSavePath + NowCaseno+'\Context.dat');
+ Context_DocnoList.LoadFromFile(ImageSavePath + NowCaseno+'\Context_DocNo.dat');
+ if FileExists(ImageSavePath + NowCaseno+'\CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(ImageSavePath + NowCaseno+'\CustomDocNo.dat');
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno); //201408280改
+ DrawDocItem2(MytreeNode1,NowCaseno);
+
+ //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
+ P := ContextList.Count;
+ MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,p]);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ NewTreeNodeRefresh;
+ TreeView1Click(self);
+
+ end;
+ //Showmessage(_Msg('刪除完成')); //20101101 User要求拿掉
+end;
+
+procedure TCB_IMGPSScanX.PM509Click(Sender: TObject);
+begin
+ PM401Click(nil);
+end;
+
+procedure TCB_IMGPSScanX.PM510Click(Sender: TObject);
+begin
+ DeskewImg(DisplayISB.Graphic);
+ DisplayISB.SaveToFile(DisplayISB.FileName);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+end;
+
+procedure TCB_IMGPSScanX.PopupMenu1Popup(Sender: TObject);
+begin
+ PM101.Visible := False; //刪除
+ PM102.Visible := False; //修改案件編號
+ PM103.Visible := False; //掃瞄器加入影像
+ PM104.Visible := False; //檔案加入影像
+ PM106.Visible := False; //複製文件至其他編號
+ PM107.Visible := False; //寫備註
+ PM108.Visible := False; //歸類
+ PM109.Visible := False; //檢核此筆
+ PM110.Visible := False; //新增自訂文件
+ PM111.Visible := False; //修改份數
+
+ if (FMode = 'SAMPLESCAN') then Exit;
+
+ if TreeView1.Selected = nil then Exit;
+ if TreeView1.Selected = NewTreeNode then //新掃瞄件
+ begin
+ if (FMode = 'NSCAN') then
+ begin
+//ShowMessage('AAAA');
+ PM101.Visible := True; //刪除
+ PM103.Visible := True; //掃瞄器加入影像
+ PM104.Visible := True; //檔案加入影像
+ end;
+
+ if FModeName=_Msg('異動件') then
+ begin
+ PM101.Visible := True;
+ end;
+// if FMode='ESCAN' then
+// begin
+// PM101.Visible := True;
+// end;
+ end
+ Else if TreeView1.Selected = MyTreeNode1 then //案件層
+ begin
+ PM101.Visible := True; //刪除
+
+ if FImgDelete='Y' then
+ begin
+ PM101.Visible:=True;
+ end;
+ if FImgDelete='N' then
+ begin
+ PM101.Visible:=false;
+ end;
+
+ if FMode='ESCAN' then
+ PM101.Visible:=false;
+
+ if FModeName=_Msg('異動件') then
+ begin
+ PM101.Visible := True;
+ end;
+
+ if not CaseDelete_Enable(NowCaseno) then //
+ PM101.Enabled := False
+ else
+ PM101.Enabled := True;
+ PM103.Visible := True; //掃瞄器加入影像
+ //PM107.Visible := True; //寫備註
+ //PM109.Visible := True; //檢核此筆
+// if FCustDocYN <> 'N' Then
+// PM110.Visible := True; //新增自訂文件 20170914 先不在tree 中做自訂文件 讓user在縮圖做
+ PM104.Visible := True; //檔案加入影像
+ if (FMode = 'NSCAN') then
+ begin
+ PM102.Visible := True; //修改案件編號
+ end;
+// if FMode='ESCAN' then
+// begin
+// PM101.Visible := True;
+// end;
+ end
+ Else if TreeView1.Selected = MyTreeNode2 then //文件層
+ begin
+ PM101.Visible := True; //刪除
+ //PM107.Visible := True; //寫備註
+ //PM109.Visible := True; //檢核此筆
+// if FCustDocYN <> 'N' Then
+// PM110.Visible := True; //新增自訂文件
+ if FImgDelete='Y' then
+ begin
+ PM101.Visible:=True;
+ end;
+ if FImgDelete='N' then
+ begin
+ PM101.Visible:=false;
+ end;
+
+ if FModeName=_Msg('異動件') then
+ begin
+ PM101.Visible := True;
+ end;
+
+ if GetUseCase('T',DisplayPath,NowDocDir) <> '' then //沒有被引用走的
+ PM101.Enabled := False //刪除
+ Else
+ PM101.Enabled := True; //刪除
+ if ((GetDocDirCopies(NowCaseno,NowDocDir) > 1) or (not DocNoNeedDiv(NowDocNo)) or (Copy(NowDocNo,1,5)='ZZZZZ')) and (NowDocNo<> 'Attach') and (NowDocNo<> 'S_Attach') then
+ PM111.Visible := True; //修改份數
+ if (FMode = 'NSCAN') then
+ PM102.Visible := True; //修改案件編號
+// if FMode='ESCAN' then
+// begin
+// PM101.Visible := True;
+// end;
+ end
+ Else if TreeView1.Selected = MyTreeNode3 then //表單層
+ begin
+ PM101.Visible := True; //刪除
+ PM104.Visible := True; //檔案加入影像
+ PM108.Visible := True; //歸類
+ PM103.Visible := True; //掃瞄器加入影像
+// if FCustDocYN <> 'N' Then
+// PM110.Visible := True; //新增自訂文件
+ if GetFormIDPage(ContextList,NowFormCode) < 1 Then
+ begin
+ PM108.Visible := False; //歸類
+ end;
+ if FImgDelete='Y' then
+ begin
+ PM101.Visible:=True;
+ end;
+ if FImgDelete='N' then
+ begin
+ PM101.Visible:=false;
+ end;
+
+ if FModeName=_Msg('異動件') then
+ begin
+ PM101.Visible := True;
+ end;
+
+ if GetUseCase('T',DisplayPath,NowDocDir) <> '' then //被引用走的
+ begin
+ PM101.Enabled := False; //刪除
+ PM104.Enabled := False; //檔案加入影像
+ PM108.Enabled := False; //歸類
+ end
+ Else
+ begin
+ PM101.Enabled := True; //刪除
+ PM104.Enabled := True; //檔案加入影像
+ PM108.Enabled := True; //歸類
+ end;
+
+ if (FMode = 'NSCAN') then
+ begin
+ PM102.Visible := True; //修改案件編號
+ end;
+ end;
+
+
+
+end;
+
+procedure TCB_IMGPSScanX.PopupMenu4Popup(Sender: TObject);
+begin
+ PM401.Visible := False;
+ PM402.Visible := False;
+ PM403.Visible := False;
+ PM404.Visible := False;
+ if FMode = 'SAMPLESCAN' then Exit;
+ if (TreeView1.Selected.Level =2) or (TreeView1.Selected.Level =3) then
+ begin
+ PM402.Visible := True;
+ PM403.Visible := True;
+ PM404.Visible := True;
+ end;
+ PM401.Visible := True;
+ if (TreeView1.Selected <> MyTreeNode2) or (FMode = 'RSCAN') then
+ PM401.Visible := False;
+end;
+
+procedure TCB_IMGPSScanX.PopupMenu5Popup(Sender: TObject);
+begin
+ PM501.Visible := False;
+ PM502.Visible := False;
+ PM503.Visible := False;
+ PM504.Visible := False;
+ PM505.Visible := False;
+ PM506.Visible := False;
+ PM507.Visible := False;
+ PM508.Visible := False;
+ PM509.Visible := False;
+ PM510.Visible := False;
+ if FMode = 'SAMPLESCAN' then Exit;
+ if (DisplayISB.FileName <> '') then
+ begin
+ PM501.Visible := True;
+ PM502.Visible := True;
+ PM503.Visible := True;
+ PM504.Visible := True;
+ //PM505.Visible := True;
+ //PM506.Visible := True;
+ //PM507.Visible := True;
+ //PM508.Visible := True;
+ //PM509.Visible := True;
+ //PM510.Visible := True;
+ end;
+ if (TreeView1.Selected <> MyTreeNode2) or (FMode = 'RSCAN') or (FMode = 'ESCAN') then
+ PM509.Visible := False;
+end;
+
+procedure TCB_IMGPSScanX.PopupMenu6Popup(Sender: TObject);
+begin
+ PM601.Visible := True; //歸類
+ PM602.Visible := True; //自行定義文件名稱
+ PM603.Visible := False; //掃描替換此頁
+ PM604.Visible := False; //歪斜矯正
+ PM605.Visible := True; //刪除
+
+// if FMode='ESCAN' then
+// begin
+// PM601.Visible := False; //歸類
+// PM602.Visible := False; //自行定義文件名稱
+// PM603.Visible := False; //掃描替換此頁
+// PM604.Visible := False; //歪斜矯正
+// PM605.Visible := False; //刪除
+// end;
+
+ if ((NowDocNo = 'Attach') or (NowDocNo = 'S_Attach')) and (FCustDocYN <> 'N') then
+ begin
+ PM602.Visible := True; //自行定義文件名稱
+ //PM603.Visible := True; //掃描替換此頁
+ PM604.Visible := True; //歪斜矯正
+ PM601.Visible := True; //歸類
+ PM605.Visible := True; //刪除
+ end;
+
+ if FModeName<>_Msg('異動件') then
+ begin
+ if (FImgDelete='Y') then
+ begin
+ PM605.Enabled:=True;
+ end;
+ if FImgDelete='N' then
+ begin
+ PM605.Enabled:=false;
+ end;
+ end;
+
+
+
+
+ if CheckSelectImg_UseCase(DisplayPath,NowCaseNo) then //選擇的影像不可有引用的
+ begin
+ PM601.Enabled := False; //歸類
+ PM605.Enabled := False; //刪除
+ end;
+
+
+end;
+
+procedure TCB_IMGPSScanX.PrePageBtnClick(Sender: TObject);
+var
+ page : Integer;
+begin
+ {page := ScrollBar1.Position;
+ Case Vmode of
+ 0 : dec(page);
+ 1 : Page := Page - 2;
+ 2 : Page := Page - 4;
+ 3 : Page := Page - 6;
+ 4 : Page := Page - 8;
+ end;
+ IF page >= ScrollBar1.min Then
+ begin
+ ScrollBar1.Position := page;
+ end
+ Else
+ ScrollBar1.Position := 1; }
+ if selectISB = nil then Exit;
+ PriorPage(SelectPage);
+ if (SelectISB.Parent.Top-4) < 0 then
+ scrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + SelectISB.Parent.Top-4;
+
+ //ISBClick(TImageScrollBox(FindComponent(ISBName+'1')));
+
+
+end;
+
+procedure TCB_IMGPSScanX.SampleScanBtnClick(Sender: TObject);
+var
+ SampleFormID : String;
+ SendData : String;
+ buttonSelected : Integer;
+begin
+ ScanMode := smSample;
+ ClearView(1);
+ Vmode := 0; //切成單頁
+ GoViewMode;
+ ScanInfo.ImageCount := 0;
+ ScanPath := SamplePath;
+ ScanCaseno := '';
+ ContextList.Clear;
+ ShowText := _Msg('範本掃描中,請稍候');
+ DataLoading(True,True);
+ SampleFormID := UpperCase(InputBox(_Msg('範本檔掃瞄輸入畫面'),_Msg('請輸入文件編號'),''));
+
+ if SampleFormIDList.IndexOf(SampleFormID)<>-1 then
+ begin
+ // Show a custom dialog
+ buttonSelected := messagedlg(SampleFormID+_Msg('已有範本,是否取代?'),mtCustom,
+ [mbYes,mbCancel], 0);
+ if buttonSelected = mrCancel then
+ begin
+ DataLoading(false,false);
+ Exit;
+ end;
+ end;
+
+ if SampleFormID <> '' then
+ begin
+ if FormIDExists(SampleFormID,False,0) then
+ begin
+ ScanSaveFilename := SampleFormID + '.tif';
+ end
+ Else
+ begin
+ Showmessage(Format(_Msg('FormID:%s尚未註冊'),[SampleFormID]));
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ DataLoading(false,false);
+ Exit;
+ end;
+ SampleAnchorMode := FormID2Anchor(SampleFormID);
+
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+//ShowMessage('AAAAA');
+ Try
+ StatrTwainScan;
+ Except
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ end;
+
+ if (ISB1.FileName <> '') and FileExists(SamplePath+SampleFormID+'.tif') then
+ begin
+ ShowText := _Msg('範本傳送中,請稍候');
+ DataLoading(True,True);
+ //多存一份jpg
+ ImageScrollBox1.LoadFromFile(SamplePath+SampleFormID+'.tif',1);
+ BWTif2Jpg(ImageScrollBox1.Graphic);
+ ImageScrollBox1.SaveToFile(SamplePath+SampleFormID+'.jpg');
+ //多存一份jpg
+
+ NowWork_No := FormCode2WorkNo(SampleFormID);
+ SendData := 'data='+FData+'&verify='+FVerify+'&work_no='+FWork_no+'&file_name='+SampleFormID+'.tif';
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.tif',FReWrite,Memo1,False) then
+ begin
+ Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
+ DataLoading(False,False);
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
+ DataLoading(False,False);
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
+ DataLoading(False,False);
+ Exit;
+ end;
+
+ if FileExists(SamplePath+SampleFormID+'.jpg') then //傳送JPG影像
+ begin
+ SendData := 'data='+FData+'&verify='+FVerify+'&work_no='+FWork_no+'&file_name='+SampleFormID+'.jpg';
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.jpg',FReWrite,Memo1,False) then
+ begin
+ Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
+ DataLoading(False,False);
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
+ DataLoading(False,False);
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
+ DataLoading(False,False);
+ Exit;
+ end;
+ end;
+ Showmessage(_Msg('傳送完成'));
+ end;
+ end;
+ DataLoading(False,False);
+
+end;
+
+procedure TCB_IMGPSScanX.ScrollBar1Change(Sender: TObject);
+begin
+ Exit;
+ If (TreeView1.Selected = MyTreenode1) or (TreeView1.Selected.ImageIndex = 6) Then
+ begin
+ view_image_FormCode(DisplayPath,'ShowAll',ScrollBar1.Position,1);
+ end
+ Else IF (TreeView1.Selected = MyTreenode2) then
+ begin
+ view_image_FormCode(DisplayPath,NowDocNo,ScrollBar1.Position,1);
+ end
+ Else if (TreeView1.Selected = MyTreenode3) then
+ begin
+ view_image_FormCode(DisplayPath,NowFormCode,ScrollBar1.Position,1);
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.ScrollBox1MouseEnter(Sender: TObject);
+begin
+ScrollBox1.SetFocus;
+end;
+
+procedure TCB_IMGPSScanX.SelectScanBtnClick(Sender: TObject);
+begin
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ scanner.SelectScanner;
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+end;
+
+procedure TCB_IMGPSScanX.StatusBar1DblClick(Sender: TObject);
+begin
+ Button3.Visible := not Button3.Visible;
+ Button4.Visible := not Button4.Visible;
+ if (GetKeyState(VK_CONTROL) < 0) Then
+ begin
+ ExportBt.Visible := not ExportBt.Visible;
+ ImportBt.Visible := not ImportBt.Visible;
+ end
+ Else
+ begin
+ Memo1.Visible := not Memo1.Visible;
+ Display1.Visible := not Display1.Visible;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.ActiveFormCreate(Sender: TObject);
+var IScrollBox : TImageScrollBox;
+ i :integer;
+begin
+ {HotKeyId1 := GlobalAddAtom('MyHotKey1')-$C000;
+ HotKeyId2 := GlobalAddAtom('MyHotKey2')-$C000;
+ HotKeyId3 := GlobalAddAtom('MyHotKey3')-$C000;
+ HotKeyId4 := GlobalAddAtom('MyHotKey4')-$C000;
+ RegisterHotKey(handle,HotKeyId1,0,VK_UP); //printscreen
+ RegisterHotKey(handle,HotKeyId1,0,VK_Down); //printscreen }
+ PostMessage(Handle,WM_ACTIVATE,WA_CLICKACTIVE,0);
+ vmode := 1;
+ DesableImage;
+ For i:= 1 to 8 do begin
+ IScrollBox := TImageScrollBox( FindComponent('ISB'+IntToStr(i)));
+ IScrollBox.MouseMode := mmUser;
+ iScrollBox.ZoomMode := zmFullPage;
+ end;
+ Sleep(500);
+ Timer1.Enabled := True;
+end;
+
+procedure TCB_IMGPSScanX.ActiveFormKeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ if Edit1.Focused then
+ begin
+ if selectISB = nil then Exit;
+
+ if (Key =VK_UP) then
+ begin
+ PriorPage(SelectPage);
+ if (SelectISB.Parent.Top-4) < 0 then
+ scrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + SelectISB.Parent.Top-4;
+
+ //ISBClick(TImageScrollBox(FindComponent(ISBName+'1')));
+ end;
+ if (Key =VK_Down) then
+ begin
+ NextPage(SelectPage);
+ if SelectISB.Parent.Top+SelectISB.Parent.Height+4 > scrollBox1.Height then
+ ScrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + (SelectISB.Parent.Top+SelectISB.Parent.Height-ScrollBox1.Height+8);
+ //scrollBox1.VertScrollBar.ScrollPos := SelectISB.Parent.Top+SelectISB.Parent.Height;
+ //ISBClick(TImageScrollBox(FindComponent(ISBName+'2')));
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.AddAttFileLBClick(Sender: TObject);
+var
+ i : Integer;
+ Addfile : String;
+begin
+ OpenDialog1.Filter := 'PDF files|*.pdf';
+ OpenDialog1.Options := [ofAllowMultiSelect];
+ if OpenDialog1.Execute then
+ begin
+ ShowText :=_Msg('檔案加入中,請稍候');
+ DataLoading(True,True);
+ for i := 0 to OpenDialog1.Files.Count - 1 do
+ begin
+ AddFile := HTTPEncode(UTF8Encode(ExtractFileName(OpenDialog1.Files.Strings[i])));
+ if FileExists(ImageSavePath+NowCaseno+'\'+AddFile) then
+ begin
+ if Messagedlg(Format(_Msg('%s己存在,是否覆蓋??'),[Addfile]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel Then
+ Continue;
+ SetAttContextList('D',-1,NowCaseno,AddFile);
+ end;
+ // AttFileGB.Visible := True; //附加電子檔窗 //20120207楊玉說不在這加電子檔先拿掉
+ // Splitter2.Visible := True;
+ CopyFile(Pchar(OpenDialog1.Files.Strings[i]),Pchar(ImageSavePath+NowCaseno+'\'+AddFile),False);
+ SetAttContextList('A',-1,NowCaseno,AddFile);
+ LoadAttFile(NowCaseno);
+ end;
+ end;
+ DataLoading(False,False);
+end;
+
+procedure TCB_IMGPSScanX.AddCredit1RGClick(Sender: TObject);
+begin
+ if DisplayPath <> '' then
+ begin
+ Case AddCredit1RG.ItemIndex of
+ -1:Case_loandoc := '';
+ 0:Case_loandoc := 'Y';
+ 1:Case_loandoc := 'N';
+ end;
+ WriteCaseIndex(DisplayPath);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.AddScanBtnClick(Sender: TObject);
+var
+ P,v : Integer;
+begin
+ IF not InitialOk Then
+ begin
+ Showmessage(_Msg('資訊尚未下載完成,請稍候或重新進入'));
+ Exit;
+ end;
+ if MyTreeNode1 = nil then
+ begin
+ Showmessage(_Msg('請先選擇案件'));
+ Exit;
+ end;
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ ScanMode := smInsert;
+ ScanInfo.ImageCount := ContextList.Count;
+ ScanPath := DisplayPath;
+ ScanCaseno := NowCaseno;
+ ScanDocDir := NowDocDir;
+ Try
+ StatrTwainScan;
+ Except
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ end;
+ Panel1.Enabled := True;
+ Panel2.Enabled := True;
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
+ //P := ContextList.Count;
+ GetCase_PageCount(CaseCount,PageCount);
+ v := Pos('-',NewTreeNode.Text);
+ NewTreeNode.Text := Format(_Msg('%s-共%d筆共%d頁'),[Copy(NewTreeNode.Text,1,v-1),CaseCount,PageCount]);
+ MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseno)]);
+
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ SetDocDirtoSelected(MyTreeNode1,FirstDocDir);
+ TreeView1Click(self);
+end;
+
+procedure TCB_IMGPSScanX.AttListBoxClick(Sender: TObject);
+begin
+ DelAttFileLB.Enabled := False;
+ if AttListBox.ItemIndex >= 0 then
+ DelAttFileLB.Enabled := True;
+end;
+
+procedure TCB_IMGPSScanX.AttListBoxDblClick(Sender: TObject);
+var
+ AttFile : String;
+begin
+ if AttListBox.ItemIndex < 0 then Exit;
+
+ AttFile := HTTPEncode(UTF8Encode(AttListBox.Items.Strings[AttListBox.ItemIndex]));
+ if FileExists(DisplayPath+AttFile) then
+ ShellExecute(Application.Handle,'open',PChar(DisplayPath+AttFile),nil,nil,SW_SHOW)
+ else
+ Showmessage(Format(_Msg('找不到檔案:%s'),[AttFile]));
+end;
+
+procedure TCB_IMGPSScanX.BtnMouseEnter(Sender: TObject);
+begin
+ AddToolTip(TBitBtn(Sender).Handle,nil,0,Pchar(TBitBtn(Sender).Hint),nil,0,0);
+end;
+
+procedure TCB_IMGPSScanX.Button3Click(Sender: TObject);
+begin
+ //Showmessage(CreateDocNo_Info(NowCaseNo)+#13+'******'+#13+CreateCustDocNo_Info(NowCaseNo));
+ //Showmessage(NowSelectFileList.Text);
+ //SetIn_WH_DocNo;
+ //CreateIn_WH(self.NowCaseno);
+ //Create_Cust_DocDir(NowCaseNo);
+ //Showmessage(self.GetDocNoDir(self.DisplayPath,'111'));
+ //Case2upload(NowCaseNo);
+ //mkdir(DisplayPath+'Test\');
+ //Download2Case(DisplayPath+'Upload\',DisplayPath+'Test\');
+ //CreateFormID_FormName(DisplayPath); //產生FormID_FormName.dat
+ //CreateDocNo_DocName(DisplayPath); //產生DocNo_Name.dat
+ //Showmessage(CreateDocNo_Info(DisplayPath)); //產生 Docno,份數,頁數;Docno,份數,頁數 的回傳字串
+ //lb1.Caption:='AAAAAAAAAAA';
+ //Showmessage(CreateDocnoFrom_Info(NowCaseno));
+ //Showmessage(self.CreateCustDocNoFrom_Info(NowCaseno));
+ //ShowMessage('FMaxUploadSize='+FMaxUploadSize);
+ //initkscan;
+ showmessage('FUrl='+FUrl+#10#13+
+ 'FCaseID='+FCaseID+#10#13+
+ 'FMode='+FMode+#10#13+
+ 'FModeName='+FModeName+#10#13+
+ 'FWork_no='+FWork_no+#10#13+
+ 'FUserID='+FUserID+#10#13+
+ 'FUserName='+FUserName+#10#13+
+ 'FUserUnit='+FUserUnit+#10#13+
+ 'FData='+FData+#10#13+
+ 'FVerify='+FVerify+#10#13+
+ 'FReWrite='+FReWrite+#10#13+
+ 'FLanguage='+FLanguage+#10#13+
+ 'FLoanDoc_Value='+FLoanDoc_Value+#10#13+
+ 'FLoanDoc_Enable='+FLoanDoc_Enable+#10#13+
+ 'FUseProxy='+FUseProxy+#10#13+
+ 'FC_DocNoList='+FC_DocNoList+#10#13+
+ 'FC_DocNameList='+FC_DocNameList+#10#13+
+ 'FFixFileList='+FFixFileList+#10#13+
+ 'FIs_In_Wh='+FIs_In_Wh+#10#13+
+ 'FOldCaseInfo='+FOldCaseInfo+#10#13+
+ 'FPrintyn='+FPrintyn+#10#13+
+ 'FIs_OldCase='+FIs_OldCase+#10#13+
+ 'FCustDocYN='+FCustDocYN);
+ ShowMessage('FImgDPI='+IntToStr(FImgDPI)+#10#13+
+ 'FScanColor='+ IntToStr(FScanColor)+#10#13+
+ 'FFileSizeLimit='+ IntToStr(FFileSizeLimit) +#10#13+
+ 'FCaseNoLength='+ IntToStr(FCaseNoLength) +#10#13+
+ 'FImgDelete='+ FImgDelete+#10#13+
+ 'FIsExternal='+ FIsExternal+#10#13+
+ 'FWH_category='+FWH_category+
+ 'FCheck_main_form='+ FCheck_main_form+#10#13+
+ 'FMaxUploadSize='+FMaxUploadSize);
+ //FImgDelete:='Y';
+ LoadImgFile;
+ { ShowMessage('UpLPoint='+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+#10#13+
+ 'UpRPoint='+IntToStr(UpRPoint.X)+','+IntToStr(UpRPoint.Y)+#10#13+
+ 'DownLPoint='+IntToStr(DownLPoint.X)+','+IntToStr(DownLPoint.Y)+#10#13+
+ 'DownRPoint='+IntToStr(DownRPoint.X)+','+IntToStr(DownRPoint.Y));
+ }
+end;
+
+procedure TCB_IMGPSScanX.Button4Click(Sender: TObject);
+var
+ i:integer;
+ str:String;
+begin
+ //Showmessage(self.Doc_Inf_List.Text);
+ //LoadImgFile;
+ //LoadImgFile1;
+ //ISB1.MouseMode:=mmAmplifier;
+
+ str:='';
+ for I := 1 to 11 do // 看 OMRErrInfo 的內容
+ begin
+ str:=str+BoolToStr(OMRErrInfo[i].Display,true)+','
+ +BoolToStr(OMRErrInfo[i].Ignore,true)+','+OMRErrInfo[i].Info+','
+ +OMRErrInfo[i].Mode+#10#13;
+ end;
+ ShowMessage('OMRErrInfo='+str);
+ ShowMessage('Doc_Inf_List='+Doc_Inf_List.Text);
+ ShowMessage('DM_FORM_INF_List='+DM_FORM_INF_List.Text) ;
+ ShowMessage('FORM_INF_List='+FORM_INF_List.Text) ;
+ ShowMessage('CHECK_RULE_INF_List='+CHECK_RULE_INF_List.Text) ;
+ ShowMessage('MEMO_INF_List='+MEMO_INF_List.Text) ;
+ ShowMessage('WORK_INF_List='+WORK_INF_List.Text) ;
+ ShowMessage('LASTEST_FORM_INF_List='+LASTEST_FORM_INF_List.Text) ;
+ ShowMessage('SampleFormIDList='+SampleFormIDList.Text);
+ ShowMessage('ExistImgList='+ExistImgList.Text);
+ ShowMessage('LastInitFormidList='+LastInitFormidList.Text);
+ ShowMessage('IN_WH_DocNoList='+IN_WH_DocNoList.Text);
+
+// SampleFormIDList.Add('31A00101011706A');
+// SampleFormIDList.Add('31A00101021706A');
+// SampleFormIDList.Add('31A00101031706A');
+end;
+
+procedure TCB_IMGPSScanX.Button5Click(Sender: TObject);
+begin
+ GetftpInfo(NowCaseno,'upload');
+ SetFtpInfo;
+ IIS_Ftp.FtpsConnect;
+
+ IIS_Ftp.FtpsToMain(FFtpExtraPath,NowCaseno+'.pdf','d:\1.pdf',display1);
+end;
+
+procedure TCB_IMGPSScanX.Button6Click(Sender: TObject);
+begin
+ GetftpInfo(NowCaseno,'download');
+ SetFtpInfo;
+ IIS_Ftp.FtpsConnect;
+ IIS_Ftp.FtpsCWD(IIS_Ftp.FtpPath);
+ IIS_Ftp.FtpsReceive(NowCaseNo+'.zip','d:\'+NowCaseNo+'.zip');
+
+
+end;
+
+procedure TCB_IMGPSScanX.ExportBtClick(Sender: TObject);
+var
+ SendData : String;
+ EnCodeDateTime : String;
+ S : TStringlist;
+ SFileName,VFileName : String;
+begin
+ SFileName := En_DecryptionStr_Base64('E','MPSLIC_SCAN.lic','9338430');
+ VFileName := En_DecryptionStr_Base64('E','MPSLIC_VIEW.lic','9338430');
+ IIS_File2Web.S_LicEnName := SFileName;
+ IIS_File2Web.V_LicEnName := VFileName;
+
+ /////下載MPSLIC_SCAN.lic //////
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+
+
+ //SendData := 'checktime='+EnCodeDateTime+'&workno=CW&formid=MPSLIC_SCAN.lic'+'&mode=sample';
+ //if not dnFile(HTTPSClient,Furl,'servlet/CWC03',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&work_no=PLN&file=MPSLIC_SCAN.lic';
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ Showmessage(_Msg('檢查註冊檔案時,網路發生錯誤!!')+_Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason);
+ Exit;
+ end;
+ /////下載MPSLIC_SCAN.lic /////
+
+ /////下載MPSLIC_VIEW.lic //////
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ //SendData := 'checktime='+EnCodeDateTime+'&workno=CW&formid=MPSLIC_VIEW.lic'+'&mode=sample'; //這裡改成必傳CW 20121212
+ //if not dnFile(HTTPSClient,Furl,'service/slic/SLIC04/sample',SendData,LngPath+VFileName,FReWrite,Memo1,False,DownImgStatus) then
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&work_no=PLN&file=MPSLIC_VIEW.lic';
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+VFileName,FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ Showmessage(_Msg('檢查註冊檔案時,網路發生錯誤!!')+_Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason);
+ Exit;
+ end;
+ /////下載MPSLIC_VIEW.lic /////
+
+ ////壓zip/////
+ S := TStringlist.Create;
+ try
+ S.Add(En_DecryptionStr_Base64('E',GetDate,'9338430'));
+ S.Add(SFileName);
+ S.Add(VFileName);
+ S.SaveToFile(LngPath+'mps.dat');
+ S.Clear;
+ S.Add(LngPath+'mps.dat');
+ S.Add(LngPath+SFileName);
+ S.Add(LngPath+VFileName);
+ if FileExists(LngPath+'mps.zip') then
+ DeleteFile(LngPath+'mps.zip');
+ ExecuteZip_Pwd(LngPath+'mps.zip',LngPath,S,False,False,'9338430');
+
+ finally
+ S.Free;
+ DeleteFile(LngPath+SFileName);
+ DeleteFile(LngPath+VFileName);
+ DeleteFile(LngPath+'mps.dat');
+ end;
+ ////壓zip//////
+ Showmessage(_Msg('匯出完成,匯出檔案:')+LngPath+'mps.zip');
+end;
+
+procedure TCB_IMGPSScanX.ImportBtClick(Sender: TObject);
+var
+ SendData : String;
+ EnCodeDateTime : String;
+ S : TStringlist;
+ SFileName,VFileName : String;
+ OpenDialog1 : TOpenDialog;
+ ZipPath : String;
+ ZipFile,ZipName : String;
+ LicName : String;
+ i : Integer;
+begin
+ OpenDialog1 := TOpenDialog.Create(self);
+ S := TStringlist.Create;
+ try
+ OpenDialog1.Filter := 'Zip files (*.zip)|*.ZIP';
+ if OpenDialog1.Execute then
+ begin
+ ZipFile:= ExtractFileName(OpenDialog1.FileName);
+ ZipName := Copy(ZipFile,1,length(ZipFile)-length(ExtractFileExt(OpenDialog1.FileName)));
+ ZipPath := LngPath+ZipName+'\';
+
+ str2dir(ZipPath);
+ if not ExecuteUnZip_Pwd(OpenDialog1.FileName,ZipPath,False,'9338430') then
+ Showmessage(_Msg('無法解壓縮'));
+ if not FileExists(ZipPath+'mps.dat') then
+ begin
+ Showmessage(_Msg('格式不符,無法匯入'));
+ Exit;
+ end;
+ S.LoadFromFile(ZipPath+'mps.dat');
+ if (En_DecryptionStr_Base64('D',S.Strings[0],'9338430')<> ServerDate) then
+ begin
+ Showmessage(_Msg('檔案過期,無法匯入'));
+ Exit;
+ end;
+
+ for i := 1 to S.Count -1 do
+ begin
+ LicName := En_DecryptionStr_Base64('D',S.Strings[i],'9338430');
+ RenameFile(ZipPath+S.Strings[i],ZipPath+LicName);
+ if (LicName = 'MPSLIC_SCAN.lic') or (LicName = 'MPSLIC_VIEW.lic') then
+
+ /////上傳MPSLICXXXX.lic ////
+ //if not upFile(HTTPSClient,FUrl,'servlet/CWC04','formid='+LicName+'@workno=CW@mode=sample','file',ZipPath+LicName,FReWrite,Memo1,False) then
+ //begin
+ SendData := 'data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&work_no=PLN&file_name='+LicName;
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',ZipPath+LicName,FReWrite,Memo1,False) then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
+ DataLoading(False,False);
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
+ DataLoading(False,False);
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
+ DataLoading(False,False);
+ Exit;
+ end;
+ /////上傳MPSLICXXXX.lic /////
+ end;
+ end;
+ Finally
+ OpenDialog1.Free;
+ S.Free;
+ _DelTree(ZipPath);
+ end;
+ Showmessage(_Msg('匯入完成'));
+end;
+
+procedure TCB_IMGPSScanX.HotKeyDown (var Msg : TMessage);
+begin
+
+end;
+
+Function TCB_IMGPSScanX.FindISB2View(Vmode:Integer):TImageScrollBox; //找空的ISB來顯示
+var
+ i,n : Integer;
+ ISB : TImageScrollBox;
+begin
+ case Vmode of
+ 0 : n := 1;
+ 1 : n := 2;
+ 2 : n := 4;
+ 3 : n := 6;
+ 4 : n := 8;
+ end;
+ for i := 1 to 8 do
+ begin
+ if i > n then Break;
+ ISB := TImageScrollBox(FindComponent('ISB'+inttostr(i)));
+ if (i = n) and (ISB.FileName <> '') then
+ begin
+ clearView(i);
+ Result := ISB1;
+ end
+ Else if ISB.FileName = '' then
+ Result := ISB;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ViewMouseMode(v:Integer);
+var
+ i : Integer;
+ Md : TMouseMode;
+ ISB : TImageScrollBox;
+begin
+//ShowMessage(IntToStr(v));
+ case v of
+ -1 : Md := TMouseMode(mmUser);
+ 0 : Md := TMouseMode(mmAmplifier);
+ 1 : Md := TMouseMode(mmZoom);
+ 2 : Md := TMouseMode(mmDrag);
+ 3 : Md := TMouseMode(mmR270);
+ 4 : Md := TMouseMode(mmR180);
+ 5 : Md := TMouseMode(mmR90);
+ 6 : Md := TMouseMode(mmDelete);
+ end;
+ for i := 1 to 8 do
+ begin
+ ISB := TImageScrollBox(FindComponent('ISB'+inttostr(i)));
+ ISB.MouseMode := TMouseMode(Md);
+ //Label3.Caption:='v='+IntToStr(v)+' time'+FormatDateTime('yyyy/mm/dd HH:MM:SS', now);
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.GoViewMode;
+begin
+ case VMode of
+ 0: DisplayMode(VMode,1,1,Panel9);
+ 1: DisplayMode(VMode,1,1,Panel9);
+ 2: DisplayMode(VMode,2,2,Panel9);
+ 3: DisplayMode(VMode,2,3,Panel9);
+ 4: DisplayMode(VMode,2,4,Panel9);
+ end;
+end;
+
+
+Procedure TCB_IMGPSScanX.SetFormID_DocNo; //將FormID及Docno抽出來另存入list裡 20130403增加
+var
+ i : Integer;
+begin
+ for i := 1 to FORM_INF_List.Count-1 do
+ begin
+ FormID_List.Add(GetSQLData(FORM_INF_List,'T1.FORM_ID',i));
+ DocNo_List.Add(GetSQLData(FORM_INF_List,'T1.DOC_NO',i));
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.DeleteFormCodeFile(CaseID,DocDir,FormID:String); //刪除指定FormID文件
+var
+ i: Integer;
+ FileList : TStringlist;
+begin
+ FileList := TStringlist.Create;
+ try
+ FileList.Clear;
+ if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
+ FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
+
+ for i := FileList.Count - 1 downto 0 do
+ begin
+ if FileName2FormCode(FileList.Strings[i]) = FormID then
+ begin
+ if (FMode = 'ESCAN') and (FModeName<>_Msg('異動件')) then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\'+DocDir+'\'+FileList.Strings[i]) then
+ begin
+ //ShowMessage('有圖為非當次掃瞄,不可刪除');
+ Break;
+ end;
+ end;
+//ShowMessage(FileList.Strings[i]);
+ DeleteImageFile(ImageSavePath+CaseID+'\'+DocDir+'\',FileList.Strings[i],CaseID);
+ end;
+ end;
+ finally
+ FileList.Free;
+ end;
+ ReSortFileName(ImageSavePath+CaseID+'\'+DocDir+'\');
+ {for i := ContextList.Count - 1 downto 0 do
+ begin
+ FName := ContextList.Strings[i];
+ if FormID = 'Err' then //刪未註冊文件
+ begin
+ If not FormIDExists(FileName2FormCode(FName),False,0) Then
+ begin
+ DeleteFile(Path+FName);
+ ContextList.Delete(i);
+ end;
+ end
+ Else
+ begin
+ If FormID = FileName2FormCode(FName) then
+ begin
+ DeleteFile(Path+FName);
+ ContextList.Delete(i);
+ end;
+ end;
+ end;
+ ContextList.SaveToFile(Path+'Context.dat');
+ ReSortFileName(Path); }
+end;
+
+Function TCB_IMGPSScanX.FindFormCodePages(CaseID,FormCode:String):Integer; //計算案件裡FormID的頁數
+var
+ i,Count : integer;
+ S : TStringlist;
+ iFormCode : String;
+begin
+ Count := 0;
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+ if FWH_category='N' then
+ begin
+ if ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]) then
+ begin
+ Continue;
+ end;
+ end;
+ iFormCode := FileName2FormCode(S.Strings[i]);
+ if FormCode = iFormCode then
+ begin
+ Inc(Count);
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+ Result := Count;
+end;
+
+Function TCB_IMGPSScanX.GetDataFormCodePages(FormCode:String):Integer; //取記錄的FormcID的頁數
+begin
+ If FindSQLData(FORM_INF_List,'T1.MAX_PAGE','T1.FORM_ID',FormCode,0,FindResult) Then
+ begin
+ IF GetFindResult('T1.MAX_PAGE') = '' Then
+ Result := 9999
+ Else
+ Result := Strtoint(GetFindResult('T1.MAX_PAGE'));
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CaseReSize(CaseID:String); //案件的影像縮放
+var
+ S : TStringlist;
+ FileName : String;
+ i : Integer;
+begin
+ {if FileExists(ImageSavePath+CaseID+'\ReSize.dat') then
+ DeleteFile(ImageSavePath+CaseID+'\ReSize.dat');}
+ if FileExists(ImageSavePath+CaseID+'\Upload\AnchorError.dat') then
+ DeleteFile(ImageSavePath+CaseID+'\Upload\AnchorError.dat');
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(ImageSavePath+CaseID+'\Upload\Context.dat');
+ For i := 0 to S.Count -1 do
+ begin
+ FileName := S.Strings[i];
+ ImageReSize_FormID(CaseID,FileName); //依十字定位點做縮放
+ end;
+ finally
+ S.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ImageReSize_FormID(CaseID,FileName:String); //依十字定位點做縮放
+var
+ FormID : String;
+ DH,DW : String;
+ NowW,NowH : Integer;
+ ANCHOR : String; //是否有十字線
+ SizeStr : String;
+ S : TStringlist;
+ v,v1:Integer;
+ IsRecordMD5:Boolean;
+begin
+ IsRecordMD5:=False;
+ FormID := FileName2FormCode(FileName);
+ if FormID = '' then Exit;
+
+ IF FindSQLData(FORM_INF_List,'T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.ANCHOR','T1.FORM_ID',FormID,0,FindResult) then
+ begin
+ DH := GetFindResult('T1.FORM_HEIGHT');
+ DW := GetFindResult('T1.FORM_WIDTH');
+ ANCHOR := UpperCase(GetFindResult('T1.ANCHOR'));
+ ANCHOR := Index2Anchor(ANCHOR);
+Display1.Lines.Add(FormID+','+DH+','+DW);
+//ShowMessage('AAAAAAAAA');
+ if ((ANCHOR = 'ANCHOR') or (ANCHOR = 'FRAME')) and (DH <> '') and (DW <> '') then //有十字定位點
+ begin
+//ShowMessage('BBBBBBB');
+ ImageScrollBox1.LoadFromFile(ImageSavePath+CaseID+'\Upload\'+FileName,1);
+
+ if (FWH_category='N') and ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName) then
+ begin
+ Exit;//20171103 補件 原有的圖不作resize
+ end;
+
+ //FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH);
+ FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH,ANCHOR);
+
+ SizeStr := CheckSize(ISB_BW,UpLPoint,UpRPoint,DownLPoint,DW,DH);
+ ImageResize(ImageScrollBox1.Graphic,ISB_BW.Graphic.Width,ISB_BW.Graphic.Height);
+
+ FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH,ANCHOR);
+ v := 5;
+ v1 := length(SizeStr);
+ IF (SizeStr <> '') and (Copy(SizeStr,1,v) <> 'ERROR') then
+ begin
+//ShowMessage('CCCCC');
+ if (ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName)) and (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName))=-1) then
+ begin
+ IsRecordMD5:=True;
+ end;
+ ImageScrollBox1.SaveToFile(ImageSavePath+CaseID+'\Upload\'+FileName);
+ if IsRecordMD5 then
+ begin
+ reSizeExistImgList.add(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName));
+ end;
+//showmessage(ImageSavePath+CaseID+'\Upload\'+FileName);
+ S := TStringlist.Create; ///20110422拿掉 換成上傳才做
+ if FileExists(ImageSavePath+CaseID+'\Upload\ReSize.dat') then
+ S.LoadFromFile(ImageSavePath+CaseID+'\Upload\ReSize.dat');
+ //S.Add(FormCode2FormName(FormID)+' '+SizeStr);
+ S.Add(FileName+','+SizeStr+#8+DateTimetoStr(Now));
+ S.SaveToFile(ImageSavePath+CaseID+'\Upload\ReSize.dat');
+ S.Free;
+ end;
+ if (Copy(SizeStr,1,v) = 'ERROR') then //未找到三個定位點
+ begin
+ S := TStringlist.Create;
+ if FileExists(ImageSavePath+CaseID+'\Upload\AnchorError.dat') then
+ S.LoadFromFile(ImageSavePath+CaseID+'\Upload\AnchorError.dat');
+ S.Add(FileName+'-->'+Copy(SizeStr,V+1,V1-v));
+ S.SaveToFile(ImageSavePath+CaseID+'\Upload\AnchorError.dat');
+ S.Free;
+ end;
+
+ ImageScrollBox1.FileName := '';
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ImageReSize_tmp(FormID,FileName:String); //依十字定位點做縮放(暫存檔)
+var
+ DH,DW : String;
+ ANCHOR : String; //是否有十字線
+ SizeStr : String;
+ S : TStringlist;
+begin
+ IF FindSQLData(FORM_INF_List,'T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.ANCHOR','T1.FORM_ID',FormID,0,FindResult) then
+ begin
+ DH := GetFindResult('T1.FORM_HEIGHT');
+ DW := GetFindResult('T1.FORM_WIDTH');
+ ANCHOR := UpperCase(GetFindResult('T1.ANCHOR'));
+ ANCHOR := Index2Anchor(ANCHOR);
+ if ((ANCHOR = 'ANCHOR') or (ANCHOR = 'FRAME')) and (DH <> '') and (DW <> '') then //有十字定位點
+ begin
+ ImageScrollBox1.LoadFromFile(FileName,1);
+ SizeStr := CheckSize(ImageScrollBox1,UpLPoint,UpRPoint,DownLPoint,DW,DH);
+ IF SizeStr <> '' then
+ begin
+ ImageScrollBox1.SaveToFile(FileName);
+ end;
+ ImageScrollBox1.FileName := '';
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
+begin
+ IF ImageScrollBox1.Graphic.Empty Then Exit;
+ ISB_BW.Graphic.Assign(ImageScrollBox1.Graphic);
+ If ImageScrollBox1.Graphic.ImageFormat <> ifBlackWhite Then
+ begin
+ ConvertToBW(ISB_BW.Graphic);
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.NewTreeNodeRefresh;
+var
+ v : Integer;
+begin
+ //v := Pos('-',NewTreeNode.Text);
+ //NewTreeNode.Text := Copy(NewTreeNode.Text,1,v-1)+'-共'+inttostr(NewTreeNode.Count)+'筆';
+ GetCase_PageCount(CaseCount,PageCount);
+ v := Pos('-',NewTreeNode.Text);
+ NewTreeNode.Text := Format(_Msg('%s-共%d筆共%d頁'),[Copy(NewTreeNode.Text,1,v-1),CaseCount,PageCount]);
+end;
+
+Procedure TCB_IMGPSScanX.MyTreeNode1Refresh;
+var
+ v : Integer;
+begin
+ v := Pos('-',MyTreeNode1.Text);
+ MyTreeNode1.Text := Format(_Msg('%s-%d筆'),[Copy(MyTreeNode1.Text,1,v-1),MyTreeNode1.Count]);
+end;
+
+Procedure TCB_IMGPSScanX.MyTreeNode2ReFresh(CaseID:String);
+var
+ P : Integer;
+begin
+ //p:= ContextList.Count;
+ //MytreeNode1.Text := Format(_Msg('%s-%d頁'),[CaseID,p]);
+ DrawDocItem2(MytreeNode1,CaseID);
+ //DrawDocItem(MytreeNode1,FORM_INF_List,CaseID);
+end;
+
+Procedure TCB_IMGPSScanX.MyTreeNode3ReFresh(CaseID:String);
+begin
+
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,CaseID); //201408280改
+ DrawDocItem2(MytreeNode1,CaseID);
+ //DrawDocItem(MytreeNode1,FORM_INF_List,CaseID);
+end;
+
+Function TCB_IMGPSScanX.Node2DocNo(Node2:TTreeNode):String; //MyTreeNode2取DocNo出來
+var
+ v,v1,v2 : Integer;
+begin
+ v := Posend('{',Node2.Text);
+ v1 := Posend('}',Node2.Text);
+ v2 := Posend('-',Node2.Text);
+ Result := Copy(Node2.Text,v+1,v1-v-1);
+ IF v1 = 0 Then
+ begin
+ Result := '';
+ end;
+end;
+
+Function TCB_IMGPSScanX.Node3DocNo(Node3:TTreeNode):String; //MyTreeNode3取DocNo出來
+var
+ v,v1,v2 : Integer;
+begin
+ v := Posend('{',Node3.Parent.Text);
+ v1 := Posend('}',Node3.Parent.Text);
+ v2 := Posend('-',Node3.Parent.Text);
+ Result := Copy(Node3.Parent.Text,v+1,v1-v-1);
+ IF v1 = 0 Then
+ begin
+ Result := '';
+ end;
+end;
+
+Function TCB_IMGPSScanX.Node3FormID(Node3:TTreeNode):String; //MyTreeNode3取FormCode出來
+var
+ v,v1,v2 : Integer;
+begin
+ v := Pos('{',Node3.Text);
+ v1 := Pos('}',Node3.Text);
+ v2 := Posend('-',Node3.Text);
+ Result := Copy(Node3.Text,v+1,v1-v-1);
+ IF v1 = 0 Then
+ begin
+ Result := '';
+ end;
+end;
+
+
+Function TCB_IMGPSScanX.GetNode2Name(Node2:TTreeNode):String; //取MyTreeNode2的識別字出來(記之前點選用)
+var
+ v : Integer;
+begin
+ v := Posend('-',Node2.Text);
+ Result := Copy(Node2.Text,1,v-1);
+end;
+
+{Function TCB_IMGPSScanX.Down_Replace_Img(SPath,DPath,CaseID:String):Boolean;
+var
+ EnCodeDateTime : String;
+ DownUrl : String;
+ SC,Main_C : TStringlist;
+ i,n : Integer;
+ FormID,DocNo,Version : String;
+ OldFName,NewMainFName,NewSubFName : String;
+ AttPath : String;
+begin
+ SC := TStringlist.Create;
+ Main_C := TStringlist.Create;
+ try
+ Result := True;
+ HaveAppDoc := False;
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ DownUrl := FUrl+CaseID+'&checktime='+EnCodeDateTime;
+ if not dnFile(HTTPSClient,DownUrl,'','',DPath+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ if Memo1.Lines.Strings[0] = '1' then
+ begin
+ HttpErrStr :=_Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+ AttPath := DPath + 'AttFile\';
+ if FileExists(DPath+CaseID+'.zip') then
+ begin
+ ExecuteUnZip(DPath+CaseID+'.zip',DPath,True);
+ if FileExists(DPath+'img.zip') then
+ begin
+ ExecuteUnZip(DPath+'img.zip',DPath,False);
+ end;
+ if FileExists(DPath+'att.zip') then
+ begin
+ Str2Dir(AttPath);
+ ExecuteUnZip(DPath+'att.zip',AttPath,False);
+ end;
+ end
+ Else
+ begin
+ if ((FMode = 'FSCAN') or (FMode = 'ISCAN')) and (Memo1.Lines.Strings[0] ='NO_FILE') then //FGIS前台匯入件沒有影像是對的
+ begin
+ SC.Clear;
+ SC.SaveToFile(DPath+'Context.dat');
+ end
+ Else
+ begin
+ HttpErrStr := _Msg('找不到影像');
+ Result := False;
+ Exit;
+ end;
+ end;
+
+
+ if FileExists(SPath+'Context.dat') then
+ SC.LoadFromFile(SPath+'Context.dat');
+ for I := 0 to SC.Count - 1 do
+ begin
+ FormID := FileName2FormCode(SC.Strings[i]);
+ DocNo := FormCode2DocNo(FormID);
+ Version := FormCode2Version(FormID);
+ If FindSQLData(Doc_Inf_List,'ADD_SCAN_RULE','DOC_NO,DOC_VERSION',DocNo+','+Version,0,FindResult) Then
+ begin
+ if GetFindResult('ADD_SCAN_RULE') = 'R' then //替換的先刪再加 20101026 User由刪FormCode改刪DocNo
+ begin
+ //DeleteFormCodeFile(DPath,FormID);
+ ContextList.LoadFromFile(DPath+'Context.dat');
+ DeleteDocNoFile(DPath,DocNo);
+ end;
+ end;
+ end;
+ for I := 0 to SC.Count - 1 do //複製補充進來的影像
+ begin
+ OldFName := SC.Strings[i];
+ Main_C.LoadFromFile(DPath+'Context.dat');
+ //NewMainFName:= Add_Zoo(Main_C.Count+1,3)+Copy(OldFName,4,length(OldFName)-3);
+ NewMainFName:= Add_Zoo(Main_C.Count+1,3)+FileName2NoQuene_Filename(OldFName);
+ FormID := FileName2FormCode(OldFName);
+ DocNo := FormCode2DocNo(FormID);
+ Version := FormCode2Version(FormID);
+ If FindSQLData(Doc_Inf_List,'ADD_SCAN_RULE','DOC_NO,DOC_VERSION',DocNo+','+Version,0,FindResult) Then
+ begin
+ CopyFile(PWideChar(SPath+OldFName),PWideChar(DPath+NewMainFName),False);
+ end;
+ if FormID = '' then //附件
+ begin
+ CopyFile(PWideChar(SPath+OldFName),PWideChar(DPath+NewMainFName),False);
+ end;
+ Main_C.Add(NewMainFName);
+ Main_C.SaveToFile(DPath+'Context.dat');
+ end;
+ finally
+ SC.Free;
+ Main_C.Free;
+ end;
+ ///加入的電子檔匯入案件裡
+ if DirectoryExists(SPath+'AttFile\') then
+ AttFile_Arrange(SPath+'AttFile\',DPath+'AttFile\');
+end;}
+
+function TCB_IMGPSScanX.checkFormCodeIsCustom(path, formcode: string): boolean;
+var
+ i:integer;
+ ini : Tmeminifile;
+ str1:String;
+begin
+//ShowMessage(path);
+ ini := Tmeminifile.Create(Path+'CustomDocNo.ini');
+ str1:=ini.ReadString(Copy(formcode,1,8),'FormID','');
+//ShowMessage('str1'+str1);
+ if str1 = formcode then
+ begin
+ Result:=True;
+ end
+ else
+ begin
+ Result := False;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.InitScrollRec;
+var i : Integer;
+begin
+ for I := 1 to 8 do
+ begin
+ ScrollRec[i].HScroll := 0;
+ ScrollRec[i].VScroll := 0;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.GetScrollData(ISB:TImageScrollBox;Var HS,VS:Integer;Var iRate:Single);
+var
+ index : Integer;
+begin
+ index := strtoint(copy(ISB.Name,4,1));
+ HS := ScrollRec[Index].HScroll;
+ VS := ScrollRec[Index].VScroll;
+ iRate := ScrollRec[Index].Rate;
+end;
+
+Procedure TCB_IMGPSScanX.SetScrollData(ISB:TImageScrollBox;HS,VS:Integer;iRate:Single);
+var
+ index : Integer;
+begin
+ index := strtoint(copy(ISB.Name,4,1));
+ ScrollRec[Index].HScroll := HS;
+ ScrollRec[Index].VScroll := VS;
+ ScrollRec[Index].Rate := iRate;
+end;
+
+Procedure TCB_IMGPSScanX.FormIDReplace(CaseID,DocDir,OldFormID,NewFormID:String); //指定FormID更換成新的FormID
+var
+ i : Integer;
+ OldFileList,NewFileList : TStringlist;
+ NewDocNo,NewDocDir:String;
+ FormID : String;
+ OldFile,NewFile:String;
+ Ext : String;
+ ST1:TStringList;
+begin
+ ST1:=TStringList.Create;
+ OldFileList := TStringlist.Create;
+ NewFileList := TStringlist.Create;
+ try
+ NewDocNo := FormCode2DocNo(NewFormID);
+ NewDocDir := FindLastestDocDir(CaseID,NewDocNo);
+
+ /////20190319 Hong 原本的程式判斷怪怪的先Mark在下方,改用這段
+ if DocNoNeedDiv(NewDocNo) then //要分份數
+ begin
+ if ((FormCode2Page(NewFormID) = '01') and (GetDocDir_Page(CaseID,NewDocDir)>0)) or (NewDocDir = '') then
+ begin
+ NewDocDir := DocNo2DocNoDir(ImageSavePath + CaseID+'\',NewDocNo);
+ end
+ else
+ begin //20171016 真對補件影響 所加的判斷
+ ST1.Clear;
+ if FileExists(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat') then
+ begin
+ ST1.LoadFromFile(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat');
+ if (ST1.Count > 0) and ISExistImg(ImageSavePath + CaseID+'\'+NewDocDir+'\'+ST1.Strings[0]) then //20181210 多增加判斷ST1>0 否則會有機會出現List out of bound Hong
+ begin
+ NewDocDir := DocNo2DocNoDir(ImageSavePath + CaseID+'\',NewDocNo);
+ end;
+ end;
+ end;
+ end
+ Else //不分份數
+ begin
+ if NewDocNo <> '' then
+ NewDocDir := NewDocNo
+ else //Attach 附件
+ NewDocDir := DocNo2DocNoDir(ImageSavePath + CaseID+'\',NewDocNo);
+ end;
+
+ {if NewDocDir = '' then
+ begin
+ if DocNoNeedDiv(NewDocNo) then
+ begin
+ NewDocDir:=DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',NewDocNo);
+ end
+ else
+ begin
+ NewDocDir := NewDocNo;
+ end;
+ end;
+//ShowMessage('NewDocDir='+NewDocDir);
+ if DocNoNeedDiv(NewDocNo) and (FormCode2Page(NewFormID)='01') then
+ begin
+ NewDocDir := DocNo2DocNoDir(ImageSavePath+CaseID+'\',NewDocNo);
+ end
+ else
+ begin
+ ST1.Clear;
+ if FileExists(ImageSavePath + NowCaseno+'\'+NewDocDir+'\Context.dat') then
+ begin
+ ST1.LoadFromFile(ImageSavePath + NowCaseno+'\'+NewDocDir+'\Context.dat');
+ if ISExistImg(ImageSavePath + NowCaseno+'\'+NewDocDir+'\'+ST1.Strings[0]) then
+ begin
+ NewDocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',NewDocNo);
+ end;
+ end;
+ end; }
+ if Not DirectoryExists(ImageSavePath+CaseID+'\'+NewDocDir) then
+ begin
+ MkDir(ImageSavePath+CaseID+'\'+NewDocDir);
+ SetDocNoList('A',-1,CaseID,NewDocDir,'1');
+ end;
+ if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
+ OldFileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
+ if FileExists(ImageSavePath+CaseID+'\'+NewDocDir+'\Context.dat') then
+ NewFileList.LoadFromFile(ImageSavePath+CaseID+'\'+NewDocDir+'\Context.dat');
+ for i := 0 to OldFileList.Count - 1 do
+ begin
+ OldFile := OldFileList.Strings[i];
+ Ext := ExtractFileExt(OldFile);
+ if FileName2FormCode(OldFile) = OldFormID then
+ begin
+ NewFile := Add_Zoo(NewFileList.Count+1,3)+'_'+NewFormID+Ext;
+ CopyFile(PWideChar(ImageSavePath+CaseID+'\'+DocDir+'\'+OldFile),PWideChar(ImageSavePath+CaseID+'\'+NewDocDir+'\'+NewFile),False);
+ NewFileList.Add(NewFile);
+ SetContextList('A',-1,CaseID,NewDocDir,NewFile);
+ end;
+ end;
+ DeleteFormCodeFile(CaseID,DocDir,OldFormID);
+
+ {for i := 0 to S.Count - 1 do
+ begin
+ FormID := FileName2FormCode(S.Strings[i]);
+ if FormID = OldFormID then
+ begin
+ OldFile := S.Strings[i];
+ Ext := ExtractFileExt(OldFile);
+ //NewFile := Copy(S.Strings[i],1,3)+'_'+NewFormID+Ext;
+ NewFile := Add_Zoo(FileName2ScanPage(S.Strings[i]),3)+'_'+NewFormID+Ext;
+ ReNameFile(Path+OldFile,Path+NewFile);
+ S.Strings[i] := NewFile;
+ end;
+ end;
+ S.SaveToFile(Path+'Context.dat');
+ ContextList.LoadFromFile(Path+'Context.dat'); }
+
+ finally
+ OldFileList.Free;
+ NewFileList.Free;
+ ST1.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.PageReplaceFormID(Path,NowFormID,NewFormID:String); //選取頁更換FormID
+var
+ i,n : Integer;
+ S,S1 : TStringlist;
+ OldFile,NewFile:String;
+ Ext : String;
+begin
+ S := TStringlist.Create;
+ S1 := TStringlist.Create;
+ try
+ S.LoadFromFile(Path+'Context.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+ if NowFormID = 'ALL' then
+ S1.Add(S.Strings[i])
+ Else if NowFormID = 'Err' then
+ begin
+ if not FormIDExists(FileName2FormCode(S.Strings[i]),False,0) then
+ S1.Add(S.Strings[i])
+ end
+ Else
+ begin
+ if NowFormID = FileName2FormCode(S.Strings[i]) then
+ S1.Add(S.Strings[i])
+ end;
+ end;
+ for I := 0 to PageLV.Items.Count - 1 do
+ begin
+ if PageLV.Items.Item[i].Selected then
+ begin
+ OldFile := S1.Strings[i];
+ Ext := ExtractFileExt(OldFile);
+ //NewFile := Copy(S1.Strings[i],1,3)+'_'+NewFormID+Ext;
+ NewFile := Add_Zoo(FileName2ScanPage(S1.Strings[i]),3)+'_'+NewFormID+Ext;
+ ReNameFile(Path+OldFile,Path+NewFile);
+ for n := 0 to S.Count - 1 do
+ begin
+ if OldFile = S.Strings[n] then
+ S.Strings[n] := NewFile;
+ end;
+ end;
+ end;
+ S.SaveToFile(Path+'Context.dat');
+ ContextList.LoadFromFile(Path+'Context.dat');
+ finally
+ S.Free;
+ S1.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetFormIDPage(FileList:TStringlist;FormID:String):Integer;
+var
+ i,Cnt : Integer;
+begin
+ Cnt := 0;
+ for i := 0 to FileList.Count - 1 do
+ begin
+ if FormID = FileName2FormCode(FileList.Strings[i]) then
+ begin
+ inc(Cnt);
+ end;
+ end;
+ Result := Cnt;
+end;
+
+Procedure TCB_IMGPSScanX.WriteResize(ImgName,TxtName:String); //產生Resize.dat
+var
+ TagTxt : String;
+ RecHeight,RecWidth : String;
+ ImgHeight,ImgWidth : String;
+ S : TStringlist;
+ v,v1:Integer;
+begin
+ ImageScrollBox1.LoadFromFile(ImgName,1);
+ ImgHeight := Inttostr(ImageScrollBox1.Graphic.Height);
+ ImgWidth := Inttostr(ImageScrollBox1.Graphic.Width);
+ Try
+ TagTxt := GetTag(ImgName);
+ Except
+ TagTxt := '';
+ End;
+ if TagTxt <> '' then
+ begin
+ S := TStringlist.Create;
+ try
+ S.CommaText := TagTxt;
+ if S.Count = 2 then
+ begin
+ v := Pos(':',S.Strings[0]);
+ v1 := length(S.Strings[0]);
+ RecHeight := Copy(S.Strings[0],v+1,v1-v);
+ v := Pos(':',S.Strings[1]);
+ v1 := length(S.Strings[1]);
+ RecWidth := Copy(S.Strings[1],v+1,v1-v);
+ end;
+ S.Clear;
+ if FileExists(TxtName) then
+ S.LoadFromFile(TxtName);
+ if (RecHeight <> '') and (RecWidth <> '') and ((RecHeight<>ImgHeight) or (RecWidth<>ImgWidth)) then
+ S.Add(ExtractfileName(ImgName)+',原長:'+RecHeight+',原寬:'+RecWidth+',長變動:'+ImgHeight+',寬變動:'+ImgWidth);
+ S.SaveToFile(TxtName);
+ finally
+ S.Free;
+ end;
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.BarCode2FormID : String; //Barcode依規則轉成FormID
+var
+ i : Integer;
+ FormID : String;
+begin
+ Result := ''; //沒找到
+ FormID := '';
+ for i := 1 to MpsBarcodeinf.Count do
+ begin
+ if (Length(MpsBarcodeinf.Text[i]) = FormIDLength) then
+ begin
+ FormID := MpsBarcodeinf.text[i];
+ if not FormIDAppear(FormID) then
+ FormID := '';
+ end;
+ if (FormID <> '') and FormIDExists(FormID,False,0) then //有可用的FormID就離開
+ begin
+ Result := FormID;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckFormIDExists(DocNoNode:TTreeNode;FormID:String):Boolean; //檢查FormID是否存在文件裡
+var
+ i : Integer;
+begin
+ Result := False;
+ for i := 0 to DocNoNode.Count - 1 do
+ begin
+ if FormID = Node3FormID(DocNoNode.Item[i]) then
+ begin
+ Result := True;
+ break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FormID2Anchor(FormID:String):String; //用FormID取出十字模式
+var
+ Anchor : String;
+begin
+ Result := 'NONE';
+ IF FindSQLData(FORM_INF_List,'T1.ANCHOR','T1.FORM_ID',FormID,0,FindResult) then
+ begin
+ ANCHOR := UpperCase(GetFindResult('T1.ANCHOR'));
+ end;
+ Result := Index2Anchor(Anchor);
+end;
+
+procedure TCB_IMGPSScanX.ScanDuplexCBClick(Sender: TObject);
+begin
+ ScanDuplex := ScanDuplexCB.Checked;
+ //R_W_ScanIni('W'); //user要求改成預設後不能改
+end;
+
+procedure TCB_IMGPSScanX.ScanGrayCBClick(Sender: TObject);
+begin
+
+ if ScanGrayCB.Checked then
+ begin
+ ScanColor:=ifGray256;
+ end
+ else
+ begin
+ if FScanColor = 0 then
+ begin
+ ScanColor := ifBlackWhite;
+ end;
+
+ if FScanColor = 1 then
+ begin
+ //ScanColor := ifGray256 ;
+ ScanColor := ifBlackWhite; //
+ end;
+
+
+ if FScanColor = 2 then
+ begin
+ ScanColor := ifTrueColor ;
+ end;
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.GetFormatID(CaseID: string):String;
+Var
+ S : TStringlist;
+ FormatID : String;
+begin
+ Result := '';
+ S := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then
+ begin
+ S.LoadFromFile(ImageSavePath+CaseID+'\CaseIndex.dat');
+ //Format_ID := S.Strings[5]; //主鍵值 (報價單號or續保單號or保單號碼or保險證號or原案件受編)
+ //Result := Format_ID;
+ //Handle_No := S.Strings[0]; //經辦代號
+ //Cen_Uid := S.Strings[1]; //被保人ID
+ //Cen_Cliname := S.Strings[2]; //被保人姓名
+ //Cen_Platno := S.Strings[3]; //車號
+ //Case_Priority := S.Strings[4];//案件等級
+ end;
+ finally
+ S.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.CaseHelpBtnClick(Sender: TObject);
+var
+ ErrlistForm : TErrlistForm;
+ S : TStringlist;
+ UpFormID : String;
+ Anchor : String;
+begin
+ ShowText := _Msg('處理檢核失敗中,請稍候');
+ DataLoading(True,True);
+LogFile1.LogToFile(logTimeString+'處理檢核失敗中開始');
+ ErrlistForm := TErrlistForm.Create(Self);
+ RejectCase := False;
+ S := TStringlist.Create;
+ try
+ InitialLanguage(ErrlistForm);
+ Application.ProcessMessages;
+ ErrlistForm.LogFile1.LogFile:=LogFile1.LogFile;
+ ErrlistForm.DeleteBt.Caption := ErrlistForm.DeleteBt.Caption+'(&D)';
+ ErrlistForm.iniPath := ImageSavePath + NowCaseNo+'\upload\';
+ OMRErrini2List(NowCaseno,ErrlistForm);
+ ErrlistForm.ErrListLV.ItemIndex := ErrIndex;
+ ErrlistForm.Timer1.Enabled := true;
+ if ErrlistForm.ShowModal = mrok then
+ begin
+ TransPath := ImageSavePath+NowCaseNo+'\upload\';
+ if FMode = 'ISCAN' then
+ TransPath := ImageSavePath + NowCaseNo+'\DownTemp\';
+ ShowText := NowCaseNo+_Msg('資料上傳中,請稍候');
+ DataLoading(True,True);
+
+ if FMode = 'ISCAN' then
+ begin
+ If Not TransCaseID(TransPath,NowCaseNo,True) Then //傳送案件
+ begin
+ DataLoading(False,False);
+ Exit;
+ end;
+ end
+ Else
+ begin
+ If Not TransCaseID(TransPath,NowCaseNo,True) Then //傳送案件
+ begin
+ DataLoading(False,False);
+ Exit;
+ end;
+ end;
+ CaseHelpBtn.Visible := False;
+ LoadImgFile;
+ if (FMode='NSCAN') or (FMode='DSCAN') then
+ begin
+ Showmessage(NowCaseNo+_Msg('影像上傳完成。此案已進入下一流程。'));
+ end;
+
+ if FMode='ESCAN' then
+ begin
+ Showmessage(NowCaseNo+_Msg('影像已補件完成。'));
+ end;
+
+ DataLoading(False,False);
+ end
+ Else
+ begin
+ MyTreeNode2ReFresh(NowCaseNo);
+ end;
+ finally
+ ErrlistForm.Free;
+ DataLoading(False,False);
+ S.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.CheckCaseBtnClick(Sender: TObject);
+Var
+ CaseID : String;
+ i,n,v : Integer;
+ S : TStringlist;
+begin
+ //if TreeView1.Selected = nil then Exit;
+ //if TreeView1.Selected = NewTreeNode then Exit;
+ Displaypath := ''; //20130327 修正報價單號會錯置的問題
+ S := TStringlist.Create;
+ try
+ ClearView(1);
+ ShowText := CaseID+_Msg('檢核中,請稍候');
+ DataLoading(True,True);
+ For i := 0 to NewTreeNode.Count -1 do
+ begin
+ v := posend('-',NewTreenode.Item[i].Text);
+ CaseID := Copy(NewTreenode.Item[i].Text,1,v-1);
+ ShowText := CaseID+_Msg('檢核中,請稍候');
+ DataLoading(True,True);
+ if (NewTreenode.Item[i].ImageIndex <> 7) and (NewTreenode.Item[i].ImageIndex <> 5) then //檢核完成的不再檢核
+ begin
+ If OMRCheckCase(CaseID) then //有成功
+ begin
+ S.Add('Y');
+ S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
+ end;
+ end;
+ //MyTreeNode2ReFresh(CaseID); //原本是OMR單一案件,後改成OMR全部案件 所以這個要mark
+ end;
+ LoadImgFile;
+ TreeView1Click(nil);
+ DataLoading(False,False);
+ finally
+ S.Free;
+ end;
+ Showmessage(_Msg('檢核完成'));
+end;
+
+procedure TCB_IMGPSScanX.ClearView(stkv:Integer);
+var i:integer;
+ ISB : TImageScrollBox;
+ lb : TLabel;
+begin
+ For i:= stkv to 8 do
+ begin
+ ISB := TImageScrollBox(FindComponent('ISB'+intToStr(i)));
+ ISB.FileName := '';
+ Lb := TLabel(FindComponent('Lb'+intToStr(i)));
+ Lb.Caption := '';
+ end;
+ FreePreViewISB;
+ ISB1Click(ISB1);
+end;
+
+procedure TCB_IMGPSScanX.PrtLbClick(Sender: TObject);
+var
+ Width : Double;
+ Height : Double;
+ i : Integer;
+ DocDirList,FileList :TStringlist;
+ iDocDir,iDocNo : String;
+ PrtDialog : TPrintDialog;
+ S : String;
+begin
+ ShowText := _Msg('列印中,請稍候');
+ DataLoading(True,True);
+ Case2upload(NowCaseNo); //產生原影像結構
+
+
+ //ontextList.LoadFromFile(ImageSavePath+NowCaseNo+'\Upload\Context.dat');
+
+ PrintForm := TPrintForm.create(Self);
+ DocDirList := TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ FileList.LoadFromFile(ImageSavePath+NowCaseNo+'\Upload\Context.dat');
+ DocDirList.LoadFromFile(ImageSavePath+NowCaseNo+'\Upload\DocDir.dat');
+
+ InitialLanguage(PrintForm); //載入多國語言
+ PrintForm.CheckListBox1.Items.Clear;
+ For i := 0 to FileList.Count - 1 do
+ begin
+ iDocDir := DocDirList.Strings[i];
+ iDocno := DocNoDir2DocNo(iDocDir);
+
+ if not DocNoAppear(iDocNo) then Continue;
+
+ PrintForm.CheckListBox1.Items.Add(FileList.Strings[i]);
+ if CheckFormID_Prt(FileName2FormCode(FileList.Strings[i])) then
+ PrintForm.CheckListBox1.Checked[i] := True;
+ PrintForm.ListBox1.Items.Add(Add_Zoo(i+1,3))
+ end;
+ If (PrintForm.ShowModal = mrOK) then
+ begin
+ S := '';
+ for I := 0 to PrintForm.CheckListBox1.Count -1 do
+ begin
+ if PrintForm.CheckListBox1.Checked[i] then
+ begin
+ if S = '' then
+ S := S+PrintForm.CheckListBox1.Items[i]
+ Else
+ S := S+#13+PrintForm.CheckListBox1.Items[i];
+ end;
+ end;
+ if S = '' then
+ begin
+ Showmessage(_msg('尚未選擇欲列印文件'));
+ Exit;
+ end
+ Else
+ begin
+ PrintImg(S,FUserID,ServerDate,ImageSavePath+NowCaseNo+'\Upload\');
+ If not Writelog(NowCaseNo) then
+ begin
+ //Showmessage('false');
+ end;
+ end;
+ end;
+ finally
+ DataLoading(False,False);
+ PrintForm.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.UseOldCaseLbClick(Sender: TObject);
+var
+ i,n : Integer;
+ CaseID,Year,BS_No,IS_Old : String;
+ OldCaseInfoForm : TOldCaseInfoForm;
+ OldCaseInfoList,Caseinfolist,FileList,DocNoList,iFileList,iDocNoList,iDocNo_CopiesList : TStringlist;
+ OldDocdir,OldDocNo,OldDocName,NewDocDir,FileName : String;
+ OldPath,NewPath,OldFile,NewFile:String;
+ Oldcopies:Integer;
+begin
+ OldCaseInfoForm := TOldCaseInfoForm.Create(Self);
+ OldCaseInfoList := TStringlist.Create;
+ Caseinfolist := TStringlist.Create;
+ FileList := TStringlist.Create;
+ DocNoList := TStringlist.Create;
+ iDocNo_CopiesList := TStringlist.Create;
+ iFileList := TStringlist.Create;
+ iDocNoList := TStringlist.Create;
+ OldCaseInfoForm.OldDocDirList := TStringlist.Create;
+ OldCaseInfoForm.OldDocNameList := TStringlist.Create;
+ OldCaseInfoForm.IN_WH_DocNoList := TStringlist.Create;
+ OldCaseInfoForm.OldCopiesList := TStringlist.Create;
+ try
+ InitialLanguage(OldCaseInfoForm); //載入多國語言
+ OldCaseInfoForm.Notebook1.ActivePage := 'CaseInfo';
+ OldCaseInfoForm.ImageSavePath := ImageSavePath;
+ OldCaseInfoForm.CaseID := NowCaseNo;
+ OldCaseInfoForm.Furl := Furl;
+ OldCaseInfoForm.Fdata := FData;
+ OldCaseInfoForm.FVerify := FVerify;
+ OldCaseInfoForm.FReWrite := FReWrite;
+ OldCaseInfoForm.FOldCaseInfo := FOldCaseInfo;
+
+ //OldCaseInfoList 案件編號@#,年度@#,業務別@#,是否舊件@#,文件編號[份數]@#,文件編號[份數] tab 案件編號@#,年度@#,業務別@#,是否舊件@#,文件編號[份數]@#,文件編號[份數]
+ OldCaseInfoList.StrictDelimiter := true;
+ OldCaseInfoList.Delimiter := #9;
+ OldCaseInfoList.DelimitedText := FOldCaseInfo;
+ //Showmessage(FOldCaseInfo);
+ //Showmessage(OldCaseInfoList.Text);
+ OldCaseInfoForm.IN_WH_DocNoList.Assign(IN_WH_DocNoList);
+ OldCaseInfoForm.FIs_In_Wh := FIs_In_Wh;
+ for i := 0 to OldCaseInfoList.Count - 1 do
+ begin
+ Caseinfolist:=SplitString('@#,',OldCaseInfoList.Strings[i]);
+ //Caseinfolist.Delimiter := '_';
+ //Caseinfolist.DelimitedText := OldCaseInfoList.Strings[i];
+ CaseID := Caseinfolist.Strings[0];
+ Year := Caseinfolist.Strings[1];
+ BS_No := Caseinfolist.Strings[2];
+ IS_Old := Caseinfolist.Strings[3];
+ With OldCaseInfoForm.OldCaseLV.Items.Add do
+ begin
+ Caption := CaseID;
+ SubItems.Add(Year);
+ SubItems.Add(BS_No);
+ SubItems.Add(IS_Old);
+ end;
+ end;
+
+ if OldCaseInfoForm.ShowModal = MrOk then
+ begin
+ OldPath := ImageSavePath+NowCaseNo+'\'+OldCaseInfoForm.UseCaseID+'\';
+ NewPath := ImageSavePath+NowCaseNo+'\';
+
+ iDocNoList.Clear;
+ if FileExists(NewPath+'CaseDocNo.dat') then
+ iDocNoList.LoadFromFile(NewPath+'CaseDocNo.dat');
+ if FileExists(NewPath+'CaseDocNo_Copies.dat') then
+ iDocNo_CopiesList.LoadFromFile(NewPath+'CaseDocNo_Copies.dat');
+
+ for i := 0 to OldCaseInfoForm.OldDocDirList.Count - 1 do
+ begin
+ FileList.LoadFromFile(OldPath+'Context.dat');
+ DocNoList.LoadFromFile(OldPath+'DocDir.dat');
+
+
+ OldDocName := OldCaseInfoForm.OldDocNameList.Strings[i];
+ OldDocDir := OldCaseInfoForm.OldDocDirList.Strings[i];
+ OldDocNo := DocNoDir2DocNo(OldDocDir);
+ if Copy(OldDocNo,1,5)<>'ZZZZZ' then
+ begin
+ if DocNoNeedDiv(OldDocNo) then
+ NewDocDir := DocNo2DocNoDir(NewPath,OldDocNo)
+ else
+ NewDocDir := OldDocNo;
+ end
+ Else
+ begin
+ NewDocDir := GetNewCustomDocNo(NewPath,OldDocName);
+ end;
+ SetRecordEditedDocDir('A',NowCaseNo,NewDocDir);
+ iFileList.Clear;
+ if FileExists(NewPath+NewDocDir+'\Context.dat') then
+ iFileList.LoadFromFile(NewPath+NewDocDir+'\Context.dat');
+
+ if Not DirectoryExists(NewPath+NewDocDir) then
+ begin
+
+
+ iDocNoList.Add(NewDocDir);
+ Oldcopies := GetDocDirCopies(NowCaseNo+'\'+OldCaseInfoForm.UseCaseID,OldDocDir); //舊案的CaseID 放在新案CaseID目錄裡
+ if FileExists(ImageSavePath+NowCaseNo+'\'+OldCaseInfoForm.UseCaseID+'\CaseDocNo_Copies.dat') then
+ iDocNo_CopiesList.Add(inttostr(Oldcopies))
+ else
+ begin
+ OldCopies := GetDocDircopies_Rec(OldPath,OldCaseInfoForm.UseCaseID,OldDocDir);
+ iDocNo_CopiesList.Add(inttostr(Oldcopies));
+ //iDocNo_CopiesList.Add('1');
+ end;
+ MkDir(NewPath+NewDocDir);
+ end;
+ SetUseCase('A',NewPath,NewDocDir,OldCaseInfoForm.UseCaseID,''); //NewDocDir 從哪來的
+ SetUseCase('A',OldPath,OldDocDir,'',NowCaseNo); //OldDocDir 去哪了
+ StringtoFile('Y',OldPath+'UseCase.dat'); //要上傳
+ for n := 0 to DocNoList.Count - 1 do
+ begin
+ if OldDocDir = DocNoList.Strings[n] then
+ begin
+ OldFile := FileList.Strings[n];
+ if Copy(NewDocDir,1,5)<>'ZZZZZ' then
+ NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile)
+ Else
+ NewFile := Add_Zoo(iFileList.Count+1,3)+'_'+GetCustomFormID(NewPath,NewDocDir)+ExtractFileExt(OldFile);
+
+ iFileList.Add(NewFile);
+ CopyFile(PwideChar(OldPath+OldFile),Pwidechar(NewPath+NewDocDir+'\'+NewFile),False);
+ end;
+ end;
+ iFileList.SaveToFile(NewPath+NewDocDir+'\Context.dat');
+ end;
+
+ iDocNoList.SaveToFile(NewPath+'CaseDocNo.dat');
+ iDocNo_CopiesList.SaveToFile(NewPath+'CaseDocNo_Copies.dat');
+ DrawDocItem2(MyTreeNode1,NowCaseNo);
+ //MyTreeNode1.Text := Format('%s-%d'+_Msg('頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
+ MyTreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
+ NewTreeNodeRefresh;
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ end;
+ finally
+ OldCaseInfoForm.OldDocDirList.Free;
+ OldCaseInfoForm.OldDocNameList.Free;
+ OldCaseInfoForm.OldCopiesList.Free;
+ OldCaseInfoList.Free;
+ Caseinfolist.Free;
+ FileList.Free;
+ DocNoList.Free;
+ iDocNo_CopiesList.Free;
+ iFileList.Free;
+ iDocNoList.Free;
+ OldCaseInfoForm.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.LastInitFormidListCreate(path: string);
+var
+ i:integer;
+ ST1:TStringList;
+ str1:string;
+begin
+//ShowMessage('path='+path);
+ ST1:=TStringList.Create;
+ ST1.LoadFromFile(path+'FormCode_Name.dat');
+ for I := 0 to ST1.Count - 1 do
+ begin
+ if (Pos('_',St1.Strings[i])<>1) and (Pos('_',St1.Strings[i])<>-1) then
+ begin
+ str1:=Copy(ST1.Strings[i],1,Pos('_',St1.Strings[i])-1);
+ LastInitFormidList.Add(str1);
+ end;
+ end;
+
+ ST1.Free;
+end;
+
+Function TCB_IMGPSScanX.FindDivFormCode(FormCode:String):Boolean; //找有沒有分案的條碼
+var
+ i : Integer;
+ DelBarCode : String;
+ S : TStringlist;
+ iMode : String;
+begin
+ Result := False;
+ iMode := FMode;
+ S := TStringlist.Create;
+ try
+ IF FindSQLData(FORM_INF_List,'T1.FORM_ID,T1.DIVISION','T1.FORM_ID',FormCode,0,FindResult) then
+ begin
+ S.CommaText := GetFindResult('T1.DIVISION');
+ for i := 0 to S.Count - 1 do //可能有多組
+ begin
+ if S.Strings[i] = iMode then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.SmoothCBClick(Sender: TObject);
+begin
+ if SmoothCB.Checked then
+ begin
+ Image_Smooth(ISB1.Graphic);
+ ISB1.Redraw(True);
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetCustomFormID(Path,DocNo:String):String; //取出自定文件FormID
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ Result := ini.ReadString(DocNo,'FormID','');
+ finally
+ ini.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.DelAttFileLBClick(Sender: TObject);
+var
+ AttFile : String;
+ SelectCount : Integer;
+ i : Integer;
+begin
+ SelectCount := 0;
+ for i := 0 to AttListBox.Items.Count - 1 do
+ begin
+ if AttListBox.Selected[i] then
+ inc(SelectCount);
+ end;
+ if SelectCount = 0 then
+ begin
+ Showmessage(_Msg('請選擇要刪除的電子檔'));
+ Exit;
+ end;
+
+ if SelectCount > 0 then
+ begin
+ if Messagedlg(Format(_Msg('是否刪除這%d筆??'),[SelectCount]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
+ for i := 0 to AttListBox.Items.Count - 1 do
+ begin
+ if AttListBox.Selected[i] then
+ begin
+ AttFile := HTTPEncode(UTF8Encode(AttListBox.Items.Strings[i]));
+ DeleteFile(ImageSavePath+NowCaseNo+'\'+AttFile);
+ SetAttContextList('D',-1,NowCaseno,AttFile);
+ end;
+ end;
+ end;
+ LoadAttFile(NowCaseNo);
+ Showmessage(_msg('刪除完成'));
+end;
+
+Function TCB_IMGPSScanX.CheckFormID_Prt(FormID:String):Boolean; //傳入的FormID是否預設列印
+begin
+ Result := False;
+ If FindSQLData(FORM_INF_List,'T1.IS_PRINT','T1.FORM_ID',FormID,0,FindResult) Then
+ begin
+ if GetFindResult('T1.IS_PRINT') = 'Y' Then
+ Result := True;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ErrFormtoCurrentForm(CaseID,EFormID,CFormID:String);//將舊案的錯誤FormID改正確的FormID
+var
+ DocNoList,FileList :TStringlist;
+ EDocNo,CDocNo,iDocNo,iFormID :String;
+ EDocDir,CDocDir:String;
+ OldFile,NewFile :String;
+ iPath,iiPath : String;
+ i,n : Integer;
+begin
+ EDocNo := FormCode2DocNo(EFormID);
+ CDocNo := FormCode2DocNo(CFormID);
+ DocNoList :=TStringlist.Create;
+ FileList := TStringlist.Create;
+ try
+ DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ for i := 0 to DocNoList.Count - 1 do
+ begin
+ EDocDir := DocNoList.Strings[i];
+ iDocNo := DocNoDir2DocNo(DocNoList.Strings[i]);
+ iPath := ImageSavePath+CaseID+'\'+EDocDir+'\';
+ if FileExists(iPath+'Context.dat') then //20140909漏加這個判斷造成自訂文件但沒影像會出錯誤訊息
+ FileList.LoadFromFile(iPath+'Context.dat');
+ for n := 0 to FileList.Count - 1 do
+ begin
+ iFormID := FileName2FormCode(FileList.Strings[n]);
+ if iFormID = EFormID then
+ begin
+ OldFile := FileList.Strings[n];
+ NewFile := StringReplace(FileList.Strings[n],iFormID,CFormID,[rfReplaceAll]);
+ FileList.Strings[n] := NewFile;
+ RenameFile(iPath+OldFile,iPath+NewFile);
+ FileList.SaveToFile(iPath+'Context.dat');
+ end;
+ end;
+ if iDocNo = EDocNo then
+ begin
+ CDocDir := StringReplace(EDocDir,EDocNo,CDocNo,[rfReplaceAll]);
+ iiPath := ImageSavePath+CaseID+'\'+CDocDir+'\';
+ MoveFile(PWideChar(iPath),PWideChar(iiPath));
+ DocNoList.Strings[i] := StringReplace(DocNoList.Strings[i],iDocNo,CDocNo,[rfReplaceAll]);
+ DocNoList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ //SetRecordEditedDocDir('A',CaseID,CDocNo); //20140918 yuu說改成不紀錄
+ end;
+ end;
+ finally
+ DocNoList.Free;
+ FileList.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SortDocDir_FormID(CaseID,DocDir:String); //將DocDir裡的文件編號排序
+var
+ i,n,v,ln : Integer;
+ Exists:Boolean;
+ FileList,SortFileList,FormIDList : TStringlist;
+ FormID,iFormID:String;
+ OldName,NewName : String;
+begin
+ FileList := TStringlist.Create;
+ SortFileList := TStringlist.Create;
+ FormIDList := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
+ begin
+ FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
+ ////取出FormID/////
+ for i := 0 to FileList.Count - 1 do
+ begin
+ FormID := FileName2FormCode(FileList.Strings[i]);
+ if (FormID = 'Attach') or (FormID = 'S_Attach') then Continue; //附件離開
+ Exists := False;
+ for n := 0 to FormIDList.Count - 1 do //查一下FORMID是否已經存在了
+ begin
+ if FormID = FormIDList.Strings[n] then
+ begin
+ Exists := True;
+ Break;
+ end;
+ end;
+ if not Exists then
+ FormIDList.Add(FormID);
+ end;
+ FormIDList.Sort;
+ //排序後產要更名的清單
+ for i := 0 to FormIDList.Count - 1 do
+ begin
+ iFormID := FormIDList.Strings[i];
+ for n := 0 to FileList.Count - 1 do
+ begin
+ if FileName2FormCode(FileList.Strings[n]) = iFormID then
+ begin
+ SortFileList.Add(FileList.Strings[n]+','+'@'+Add_Zoo(SortFileList.Count+1,3)+'_'+iFormID+ExtractFileExt(FileList.Strings[n]));
+ end;
+ end;
+ end;
+ FileList.Clear;
+ //更名成新順序的檔名
+ for i := 0 to SortFileList.Count - 1 do
+ begin
+ v := Pos(',',SortFileList.Strings[i]);
+ ln := Length(SortFileList.Strings[i]);
+ OldName := Copy(SortFileList.Strings[i],1,v-1);
+ NewName := Copy(SortFileList.Strings[i],v+1,ln-v);
+ RenameFile(ImageSavePath+CaseID+'\'+DocDir+'\'+OldName,ImageSavePath+CaseID+'\'+DocDir+'\'+NewName);
+ FileList.Add(NewName);
+ end;
+ //去掉@開頭
+ for i := 0 to FileList.Count - 1 do
+ begin
+ OldName := FileList.Strings[i];
+ NewName := StringReplace(OldName,'@','',[rfReplaceAll]);
+ ReNameFile(ImageSavePath+CaseID+'\'+DocDir+'\'+OldName,ImageSavePath+CaseID+'\'+DocDir+'\'+NewName);
+ FileList.Strings[i] := NewName;
+ end;
+ FileList.SaveToFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
+ end;
+ finally
+ FileList.Free;
+ SortFileList.Free;
+ FormIDList.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FormIDAppear(FormID:String):Boolean; //FormID是否可出現
+var
+ iDocNo : String;
+begin
+ Result := True;
+ iDocNo := FormCode2DocNo(FormID);
+ if (((FIs_In_Wh = 'Y') and (not DocNoIs_In_WH(iDocNo))) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and (DocNoIs_In_WH(iDocNo)))) and //非入庫掃描不看入庫文件
+ ((iDocNo <> 'Attach') and (iDocNo <> 'S_Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then
+ Result := False;
+
+ if (FIs_In_Wh='Y') and (FWH_category='Y') then //20170816 新加
+ begin
+ if (((FIs_In_Wh = 'Y') and (not DocNoIs_In_WH(iDocNo))) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and (DocNoIs_In_WH(iDocNo)))) and //非入庫掃描不看入庫文件
+ ((iDocNo <> 'Attach') and (iDocNo <> 'S_Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then
+ Result := False;
+ end;
+
+ if (FIs_In_Wh='Y') and (FWH_category='N') then //20170816 新加
+ begin
+ Result:=True;
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.ISGuideFormID(FormID:String):Boolean;
+var
+ i : Integer;
+begin
+ Result := False;
+ for i := 0 to GuideFormIDList.Count - 1 do
+ begin
+ if FormID = GuideFormIDList.Strings[i] then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.ISDivPageFormID(FormID:String):Boolean;
+var
+ i : Integer;
+begin
+ Result := False;
+
+ for i := 0 to DivPageFormIDList.Count - 1 do
+ begin
+ if FormID = DivPageFormIDList.Strings[i] then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.MoveImage_Drag(Path:String;fp,tp:Integer); //拖拉移動頁數
+var
+ i,n,inx:Integer;
+ FList,D_Flist:TStringlist;
+begin
+ FList := TStringlist.Create;
+ D_Flist := TStringlist.Create;
+ try
+ FList.LoadFromFile(Path+'Context.dat');
+ for i := 0 to FList.Count - 1 do
+ begin
+ Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);
+ Flist.Strings[i]:= '@'+Flist.Strings[i];
+ end;
+
+ D_Flist.Add(Flist.Strings[fp-1]);
+
+ {for i := 0 to ComponentCount -1 do
+ begin
+ if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
+ begin
+ inx := strtoint(Copy(TShape(Components[i]).Name,3,length(TShape(Components[i]).Name)-2));
+ D_Flist.Add(Flist.Strings[inx-1]);
+ //Renamefile(Path+Flist.Strings[inx-1],path+'@'+Flist.Strings[inx-1]);
+ end;
+ end;}
+ //Showmessage('aa');
+ for i := 0 to D_Flist.Count -1 do
+ begin
+ for n := 0 to FList.Count - 1 do
+ begin
+ //if Flist.Strings[n]=StringReplace(D_Flist.Strings[i],'@','',[rfReplaceAll]) then
+ if Flist.Strings[n]=D_Flist.Strings[i] then
+ begin
+ Flist.Delete(n);
+ Break;
+ end;
+ end;
+ end;
+ //Showmessage('bb');
+ for i := 0 to D_Flist.Count - 1 do
+ begin
+ Flist.Insert(tp-1+i,D_Flist.Strings[i]);
+ end;
+
+ Flist.SaveToFile(Path+'Context.dat');
+ //Showmessage(Flist.Text);
+ //Showmessage('CC');
+ ReSortFileName(Path);
+ TreeView1click(self);
+
+
+ finally
+ FList.Free;
+ D_Flist.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FormCode2FormName(CaseID,FormCode:String):String; //用FormCode轉成文件名稱
+var
+ i,v,ln : Integer;
+ DelBarCode : String;
+ CusDocNo,CusDocName : String;
+begin
+ Result := '';
+ if (FormCode = '') or (FormCode = 'Attach') or (FormCode = 'S_Attach') then
+ Result := _Msg('未歸類')
+ //showmessage('a');
+ //stringtofile(FORM_INF_List.Text,'D:\121.txt');
+ Else If FindSQLData(FORM_INF_List,'T1.FORM_ID,T1.FORM_DESC','T1.FORM_ID',FormCode,0,FindResult) then
+ Result := GetFindResult('T1.FORM_DESC');
+
+ ////// 到自訂文件找//////
+ if Result = '' then
+ Result := GetCustomDocName(ImageSavePath+CaseID+'\',FormCode2DocNo(FormCode));
+ {for i := 0 to Cust_DocNoList.Count - 1 do
+ begin
+ v := Pos('_',Cust_DocNoList.Strings[i]);
+ ln := Length(Cust_DocNoList.Strings[i]);
+ CusDocNo := copy(Cust_DocNoList.Strings[i],1,v-1);
+ CusDocName := Copy(Cust_DocNoList.Strings[i],v+1,ln-v);
+ if CusDocNo = FormCode2DocNo(FormCode) then
+ Result := DocNo2DocName(CusDocNo);
+
+ end;}
+
+
+ {DelBarCode := '**'+FormCode;
+ for I := 0 to FormCodeList.Count - 1 do
+ begin
+ if FindDel then //要找下架的
+ begin
+ if (FormCode = FormCodeList.Strings[i]) or (DelBarCode = FormCodeList.Strings[i]) then
+ begin
+ Result := FormNameList.Strings[i];
+ Break;
+ end;
+ end
+ Else
+ begin
+ if (FormCode = FormCodeList.Strings[i]) or (DelBarCode = FormCodeList.Strings[i]) then
+ begin
+ Result := FormNameList.Strings[i];
+ Break;
+ end;
+ end;
+ end; }
+end;
+
+Function TCB_IMGPSScanX.FormCode2FileName(FormCode:String;List:TStrings):String; //用FormCode找出檔名(第一頁)
+var
+ i : Integer;
+ v,v1 : Integer;
+begin
+ Result := '';
+ for i := 0 to List.Count - 1 do
+ begin
+ V := pos('_',List.Strings[i]);
+ v1 := pos('.',List.Strings[i]);
+ if (FormCode = '') and (V = 0)then //FormCode 為空的則找附件出來
+ begin
+ Result := List.Strings[i];
+ Break;
+ end;
+ IF FormCode = Copy(List.Strings[i],v+1,v1-v-1) then
+ begin
+ Result := List.Strings[i];
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FileName2FormCode(FileName:String):String; //從檔名取出FormCode
+var
+ v,v1 : Integer;
+begin
+ FileName := ExtractFileName(FileName);
+ v := Pos('_',FileName);
+ v1 := Pos('.',FileName);
+ if v > 0 then
+ begin
+ Result := Copy(FileName,v+1,v1-v-1);
+ end
+ Else //附件
+ begin
+ Result := '';
+ end;
+end;
+
+Function TCB_IMGPSScanX.FileName2FormName(CaseID,FileName:String):String; //從檔名取出文件名稱
+begin
+ Result := FormCode2FormName(CaseID,FileName2FormCode(FileName));
+end;
+
+Function TCB_IMGPSScanX.FormCode2DocNo(FormCode:String):String; //FormCode轉Docno
+Var
+ i : Integer;
+begin
+ Result := '';
+ for i := 0 to FormID_List.Count-1 do
+ begin
+ if FormID_List.Strings[i] = FormCode then
+ begin
+ Result := DocNo_List.Strings[i];
+ Break;
+ end;
+
+ end;
+ if (FormCode <> '') and (Result = '') then //是自訂文件
+ begin
+ Result := Copy(FormCode,1,8); //20170224 DocNo 固定長度8碼
+ end;
+
+ {If FindSQLData(FORM_INF_List,'T1.DOC_NO','T1.FORM_ID',FormCode,0,FindResult) Then //20130403太慢了..換掉
+ begin
+ Result := GetFindResult('T1.DOC_NO');
+ end;}
+end;
+
+Function TCB_IMGPSScanX.FormCode2Version(FormCode:String):String; //FormCode轉版本
+begin
+ Result := Copy(FormCode,11,5);
+end;
+
+Function TCB_IMGPSScanX.FormCode2Page(FormCode:String):String; //FormCode轉頁數
+begin
+ Result := Copy(FormCode,9,2)
+end;
+
+Function TCB_IMGPSScanX.FormCode2WorkNo(FormCode:String):String; //用FormCode取出作業別
+begin
+ Result := '';
+ If FindSQLData(FORM_INF_List,'T1.WORK_NO','T1.FORM_ID',FormCode,0,FindResult) Then
+ begin
+ Result := GetFindResult('T1.WORK_NO');
+ end;
+end;
+
+Function TCB_IMGPSScanX.CaseNode2Info(Node:TTreeNode;Mode:Char):String; //案件Node取案件編號 Mode: I:Caseno;P:Page
+var
+ v,ln : Integer;
+begin
+ //XXXXXX-XX頁
+ V := Pos('-',Node.Text);
+ ln := Length(Node.Text);
+ case Mode of
+ 'I': Result := Copy(Node.Text,1,v-1); //CaseID
+ 'P': Result := Copy(Node.Text,v+1,ln-v-1); //CasePage
+ end;
+
+end;
+
+Function TCB_IMGPSScanX.DocNode2Info(Node:TTreeNode;Mode:Char):String; //文件Node取文件代號 Mode: I:Docno;N:Docname;P:Page;G:Group
+var
+ v,v1,v2,v3,ln :integer;
+begin
+ //文件名稱@組數{文件代號}-XX頁
+ V := PosEnd('@',Node.Text);
+ v1 := PosEnd('{',Node.Text);
+ v2 := PosEnd('}',Node.Text);
+ v3 := PosEnd('-',Node.Text);
+ ln := Length(Node.Text);
+ case Mode of
+ 'I': Result := Copy(Node.Text,v1+1,v2-v1-1); //DocNo
+ 'N': Result := Copy(Node.Text,1,v-1); //DocName
+ 'P': Result := Copy(Node.Text,v3+1,ln-v3-1); //DocPage
+ 'G': Result := Copy(Node.Text,v+1,v1-v-1); //DocGroup
+ end;
+end;
+
+Function TCB_IMGPSScanX.FormNode2Info(Node:TTreeNode;Mode:Char):String; //表單Node取表單代號 Mode: I:FormID;N:FormName;P:Page
+var
+ v,v1,v2,ln :integer;
+begin
+ //表單代號{表單名稱}-XX頁
+ v := Pos('{',Node.Text);
+ v1 := PosEnd('}',Node.Text);
+ v2 := PosEnd('-',Node.Text);
+ ln := Length(Node.Text);
+ case Mode of
+ 'I': Result := Copy(Node.Text,1,v-1); //FormID
+ 'N': Result := Copy(Node.Text,v1+1,v2-v1-1); //FormName
+ 'P': Result := Copy(Node.Text,v2+1,ln-v2-1); //Page
+ end;
+end;
+
+Function TCB_IMGPSScanX.DocNoExistsinTree(CaseNode:TTreeNode;DocNo:String):Boolean; //是否己存在樹裡
+var
+ i : Integer;
+begin
+ Result := False;
+ for I := 0 to CaseNode.Count - 1 do
+ begin
+ if DocNo = DocNode2Info(CaseNode.Item[i],'I') Then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.DistinctFormCode(CaseID:String); //從案件裡的FormCode取出第一頁
+var
+ i,n : Integer;
+ LForm,OForm : String;
+ Addok : Boolean;
+ S : TStringlist;
+begin
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
+ for i := 0 to S.Count - 1 do
+ begin
+LogFile1.LogToFile(logTimeString+S.Strings[i]+' ISExistImg='+BoolToStr(ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]),true));
+LogFile1.LogToFile(logTimeString+S.Strings[i]+' reSizeExistImgList='+BoolToStr(reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1,true));
+ if FWH_category='N' then
+ begin
+ if (ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))
+ or (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1) then
+ begin
+ Continue;
+ end;
+ end;
+
+ LForm := FileName2FormCode(S.Strings[i]);
+ AddOk := True;
+ for n := 0 to OMRFileList.Count - 1 do
+ begin
+ OForm := FileName2FormCode(OMRFileList.Strings[n]);
+ if (LForm <> '') and (LForm = OForm) then
+ begin
+ AddOk := False;
+ Break;
+ end;
+ end;
+ if AddOk then
+ begin
+ OMRFileList.Add(S.Strings[i]);
+ end;
+ end;
+ finally
+ S.Free;
+ end;
+
+end;
+
+
+procedure TCB_IMGPSScanX.view_image_FormCode(Path,FormCode:String;stpage,stview:integer); //用FormCode來找影像
+var i,p:integer;
+ ISB : TImageScrollBox;
+ lb : TLabel;
+ v ,v1 : Integer;
+ page : Integer;
+ List_FormCode,Err_FormCode: String;
+ iFormID : String;
+begin
+ ShowText := _Msg('影像顯示中,請稍候');
+ DataLoading(True,True);
+
+ IF FormCode = 'ShowAll' then //顯示所有的影像 (因為附件會傳空字串,所以用ShowAll)
+ begin
+ ClearView(1);
+ CreatePreViewISB(ContextList.Count);
+ For i := Stpage-1 to ContextList.Count -1 do
+ begin
+ ISB := TImageScrollBox(FindComponent(ISBName+intToStr(stview+i)));
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+ContextList.Strings[i],1);
+
+ {GetScrollData(ISB,HS,VS,iRate);
+ if iRate = 0 then
+ ISB.ZoomMode := zmFittoPage
+ Else
+ ISB.ZoomPercent := iRate;
+ ISB.HorzScrollBar.Position := HS;
+ ISB.VertScrollBar.Position := VS;
+
+ List_FormCode := FileName2FormCode(ContextList.Strings[i]);
+ lb := TLabel(FindComponent('lb'+intToStr(stview)));
+ lb.Caption := Format(_Msg('第%s頁'),[Add_Zoo(i+1,3)]);
+ If List_FormCode = '' Then
+ lb.Caption := lb.Caption+'('+FormCode2FormName(List_FormCode)+')'
+ Else
+ lb.Caption := lb.Caption+'('+FormCode2FormName(List_FormCode)+'-'+List_FormCode+')';
+ Inc(Stview);
+ If ((VMode = 0) and (Stview>1))
+ or ((VMode = 1) and ((Stview>2)))
+ or ((VMode = 2) and ((Stview>4)))
+ or ((VMode = 3) and ((Stview>6)))
+ or ((VMode = 4) and ((Stview>8))) Then
+ break;
+ }
+ end;
+ FitPreViewISB;
+ end
+ Else //顯示指定FormCode的影像
+ begin
+ If (TreeView1.Selected <> nil) Then
+ begin
+ If Stpage = 0 Then
+ Stpage := 1;
+ Page := 0;
+ ClearView(stview);
+ If Stpage > ContextList.Count Then Exit;
+ For i := 0 to ContextList.Count -1 do
+ begin
+ List_FormCode := FileName2FormCode(ContextList.Strings[i]);
+ {iFormID := GetMainFormID(List_FormCode);
+ if iFormID <> '' then
+ List_FormCode := iFormID;}
+
+ Err_FormCode := 'NoCode';
+ if (List_Formcode <> '') and (not FormIDExists(List_Formcode,False,0)) then
+ Err_FormCode := 'Err';
+ IF (List_FormCode = FormCode) or (Err_FormCode=Formcode) or (FormCode2DocNo(List_FormCode) = FormCode) Then
+ begin
+ Inc(Page);
+ IF Page< Stpage Then
+ Continue;
+ ISB := TImageScrollBox(FindComponent('ISB'+intToStr(stview)));
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+ContextList.Strings[i],1);
+
+ GetScrollData(ISB,HS,VS,iRate);
+ if iRate = 0 then
+ ISB.ZoomMode := zmFittoPage
+ Else
+ ISB.ZoomPercent := iRate;
+ ISB.HorzScrollBar.Position := HS;
+ ISB.VertScrollBar.Position := VS;
+ {if not SortMode then
+ begin
+ SetScrollData(MPSViewX,MPSViewX.HorzScrollBarPos,MPSViewX.VertScrollBarPos,MPSViewX.ZoomPercent);
+ end;}
+ //MPSViewX.ImageZoomMode := zmFullpage;
+ //MPSViewX.AntiAliased := True;
+ lb := TLabel(FindComponent('lb'+intToStr(stview)));
+ lb.Caption := Format(_Msg('第%s頁'),[Add_Zoo(i+1,3)]);
+ If List_FormCode = '' Then
+ lb.Caption := lb.Caption+'('+FormCode2FormName(NowCaseno,List_FormCode)+')'
+ Else
+ lb.Caption := lb.Caption+'('+FormCode2FormName(NowCaseNo,List_FormCode)+'-'+List_FormCode+')';
+ Inc(Stview);
+ end;
+ If ((VMode = 0) and (Stview>1))
+ or ((VMode = 1) and ((Stview>2)))
+ or ((VMode = 2) and ((Stview>4)))
+ or ((VMode = 3) and ((Stview>6)))
+ or ((VMode = 4) and ((Stview>8))) Then
+ break;
+ end;
+ end;
+ end;
+ ISB1Click(ISB1);
+
+
+ DataLoading(False,False);
+end;
+
+procedure TCB_IMGPSScanX.view_image_DocNo(Path,DocNo,FormID:String;Pages:integer); //用DocNo來找影像
+var i,n,p:integer;
+ ISB : TImageScrollBox;
+ lb : TLabel;
+ v ,v1 : Integer;
+ List_DocNo,Trans_DocNo,List_FormCode,Form_Page: String;
+ iDocNo : String;
+ iGroupNo,page,Ct,int1 : Integer;
+ ST1:TStringList;
+begin
+ ShowText := _Msg('影像顯示中,請稍候');
+ DataLoading(True,True);
+ST1:=TStringList.Create;
+//Display1.Lines.Clear;
+ IF DocNo = 'ShowAll' then //顯示所有的影像 (因為附件會傳空字串,所以用ShowAll)
+ begin
+ ClearView(1);
+ if GetCasePage(ImageSavePath,NowCaseno) > 30 then
+ begin
+ DataLoading(False,False);
+ Exit;
+ end;
+ CreatePreViewISB(GetCasePage(ImageSavePath,NowCaseno));
+//Showmessage(inttostr(GetCasePage(ImageSavePath,NowCaseno)));
+ Ct := 0;
+ For i := 0 to CaseDocNoList.Count-1 do
+ begin
+
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ if FileExists(ImageSavePath+NowCaseno+'\EditedDocDir.dat') then
+ begin
+ ST1.LoadFromFile(ImageSavePath+NowCaseno+'\EditedDocDir.dat');
+ end;
+ end;
+
+ iDocNo := CaseDocNoList.Strings[i];
+//ShowMessage('ST1.Count='+IntToStr(ST1.Count));
+ if ST1.Count<>0 then
+ begin
+ if ST1.IndexOf(iDocNo)<>-1 then
+ begin
+ end
+ else
+ begin
+ if not DocNoAppear(DocNoDir2DocNo(iDocNo)) then continue; //20170817 這不能被註解
+ end;
+ end
+ else
+ begin
+ if not DocNoAppear(DocNoDir2DocNo(iDocNo)) then continue; //20170817 這不能被註解
+ end;
+ ContextList.Clear;
+ if FileExists(Path+iDocNo+'\Context.dat') then
+ ContextList.LoadFromFile(Path+iDocNo+'\Context.dat');
+//ShowMessage('ContextList='+ContextList.Text);
+ for n := 0 to ContextList.Count - 1 do
+ begin
+
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ if ISExistImg(Path+iDocNo+'\'+ContextList.Strings[n]) then
+ begin
+
+ if not DocNoIs_In_WH(Copy(iDocNo,1,8)) then
+ begin
+ Continue;
+ end;
+ end;
+ end;
+
+ inc(Ct);
+ ISB := TImageScrollBox(FindComponent(ISBName+intToStr(Ct)));
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+iDocNo+'\'+ContextList.Strings[n],1);
+
+ DpiResize(ISB.Graphic,36,False);
+ ISB.Redraw(true);
+
+ end;
+
+ end;
+ //if DirectoryExists(Path+'Attach') then
+ if DirectoryExists(Path+AttName) then
+ begin
+ //iDocNo := 'Attach';
+ iDocNo := AttName;
+ ContextList.Clear;
+ if FileExists(Path+iDocNo+'\Context.dat') then
+ ContextList.LoadFromFile(Path+iDocNo+'\Context.dat');
+ for n := 0 to ContextList.Count - 1 do
+ begin
+ inc(Ct);
+ ISB := TImageScrollBox(FindComponent(ISBName+intToStr(Ct)));
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+iDocNo+'\'+ContextList.Strings[n],1);
+ end;
+ end;
+
+ FitPreViewISB;
+
+ end
+ Else if (DocNo <> '') and (FormID = '') then //顯示指定DocNo+組別的影像 附件傳 Attach
+ begin //顯示 文件層下的影像
+ iDocNo := DocNo;
+ ContextList.Clear;
+ if FileExists(Path+iDocNo+'\Context.dat') then
+ ContextList.LoadFromFile(Path+iDocNo+'\Context.dat');
+
+//ShowMessage('ContextList.Count='+IntToStr(ContextList.Count));
+ CreatePreViewISB(ContextList.Count);
+//ShowMessage(IntToStr(ContextList.Count));
+ int1:=0;
+//ShowMessage(BoolToStr(DocNoIs_In_WH(Copy(iDocNo,1,8)),true));
+ For i := 0 to ContextList.Count -1 do
+ begin
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ if ISExistImg(Path+iDocNo+'\'+ContextList.Strings[i]) then
+ begin
+
+ if not DocNoIs_In_WH(Copy(iDocNo,1,8)) and ( iDocNo<>'Attach') then
+ begin
+ inc(int1);
+ Continue;
+ end;
+ end;
+ end;
+//ShowMessage(Path+iDocNo+'\'+ContextList.Strings[i]);
+ ISB := TImageScrollBox(FindComponent(ISBName+intToStr(i+1-int1)));
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+iDocNo+'\'+ContextList.Strings[i],1);
+ DpiResize(ISB.Graphic,36,False);
+ ISB.Redraw(true);
+ end;
+ FitPreViewISB;
+ end
+ Else if (FormID <> '') {and (FormID <> 'Attach')} then //顯示指定FormID的影像
+ begin
+ If (TreeView1.Selected <> nil) Then
+ begin
+ iDocNo := DocNo;
+ ContextList.Clear;
+ if FileExists(Path+iDocNo+'\Context.dat') then
+ ContextList.LoadFromFile(Path+iDocNo+'\Context.dat');
+ iGroupNo := 0;
+ page := 0;
+ Ct := 0;
+ CreatePreViewISB(Pages);
+//ShowMessage('formID page'+IntToStr(Pages)+', ContextList='+ContextList.Text);
+ For i := 0 to ContextList.Count -1 do
+ begin
+ if FileName2FormCode(ContextList.Strings[i]) = FormID then
+ begin
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+//ShowMessage(Path+iDocNo+'\'+ContextList.Strings[i]);
+//ShowMessage(BoolToStr(ISExistImg(Path+iDocNo+'\'+ContextList.Strings[i]),true));
+ if ISExistImg(Path+iDocNo+'\'+ContextList.Strings[i]) then
+ begin
+ if not DocNoIs_In_WH(FormCode2DocNo(FormID)) then
+ Continue;
+ end;
+ end;
+ inc(Ct);
+ ISB := TImageScrollBox(FindComponent(ISBName+intToStr(Ct)));
+//ShowMessage(ISB.Name);
+ ISB.AntiAliased := True;
+ if ISB.ZoomPercent > 100 then
+ ISB.AntiAliased := False;
+ ISB.LoadFromFile(Path+iDocNo+'\'+ContextList.Strings[i],1);
+ DpiResize(ISB.Graphic,36,False);
+ ISB.Redraw(true);
+
+ //NowShowFileList.Add(ContextList.Strings[i]);
+ end;
+ end;
+ FitPreViewISB;
+ end;
+ end;
+
+ if FindComponent(ISBName+'1') <> nil then
+ begin
+ ISBClick(TImageScrollBox(FindComponent(ISBName+'1')));
+ end;
+ ISB1Click(ISB1);
+ DataLoading(False,False);
+end;
+
+Function TCB_IMGPSScanX.ShapeName2PreViewISBName(SP:TShape):String; //轉出指定PreViewISBName
+begin
+ Result := ISBName+Copy(SP.Name,3,length(SP.Name)-2);
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton14Click(Sender: TObject);
+var
+ Count : Integer;
+begin
+ if not ISB1.Graphic.IsEmpty then
+ begin
+ ISB1.LoadFromFile(ISB1.FileName,1);
+ Rotate(ISB1.Graphic,270);
+ if ISB1.Graphic.ImageFormat <> ifBlackWhite then
+ begin
+ TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
+ TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
+ end
+ Else
+ ISB1.SaveToFile(ISB1.FileName);
+ ISB1.Redraw(True);
+ SelectISB.Graphic.Assign(ISB1.Graphic);
+ SelectISB.Redraw(True);
+ FitPreViewISB;
+ ISBClick(SelectISB);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton15Click(Sender: TObject);
+begin
+ if not ISB1.Graphic.IsEmpty then
+ begin
+ ISB1.LoadFromFile(ISB1.FileName,1);
+ Rotate(ISB1.Graphic,180);
+ if ISB1.Graphic.ImageFormat <> ifBlackWhite then
+ begin
+ TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
+ TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
+ end
+ Else
+ ISB1.SaveToFile(ISB1.FileName);
+ ISB1.Redraw(True);
+ SelectISB.Graphic.Assign(ISB1.Graphic);
+ SelectISB.Redraw(True);
+ FitPreViewISB;
+ ISBClick(SelectISB);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton16Click(Sender: TObject);
+begin
+ if not ISB1.Graphic.IsEmpty then
+ begin
+ ISB1.LoadFromFile(ISB1.FileName,1);
+ Rotate(ISB1.Graphic,90);
+ if ISB1.Graphic.ImageFormat <> ifBlackWhite then
+ begin
+ TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
+ TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
+ end
+ Else
+ ISB1.SaveToFile(ISB1.FileName);
+ ISB1.Redraw(True);
+ SelectISB.Graphic.Assign(ISB1.Graphic);
+ SelectISB.Redraw(True);
+ FitPreViewISB;
+ ISBClick(SelectISB);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton17Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmFitHeight;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton18Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmFitWidth;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton19Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmOriginalSize;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton20Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmFittoPage;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton21Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmPercent;
+ ISB1.ZoomPercent := 50;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton22Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmPercent;
+ ISB1.ZoomPercent := 25;
+end;
+
+procedure TCB_IMGPSScanX.SpeedButton3Click(Sender: TObject);
+begin
+ ISB1.ZoomMode := zmFullPage;
+end;
+
+Procedure TCB_IMGPSScanX.CreatePreViewISB(Count:Integer);
+var
+ ISB : TImageScrollBox;
+ Panel : TPanel;
+ i,W,H : Integer;
+ myDate : TDateTime;
+begin
+ FreePreViewISB;
+ ScrollBox1.HorzScrollBar.Visible := False;
+ W := 150;
+ H := 250;
+ for I := 1 to Count do
+ begin
+
+ if FindComponent('M_Pl'+inttostr(i))=nil then
+ begin
+ Panel := TPanel.Create(Self);
+ Panel.Name := 'M_Pl'+inttostr(i);//FormatDateTime('yyyymmddhhnnsszzz', now)
+ Panel.Left := 4;
+ Panel.Top := (i-1)*H+(6*i);
+ Panel.Height := H;
+ Panel.Width := W;
+ Panel.Parent := ScrollBox1;
+ Panel.Caption :='';
+
+ if FindComponent(ISBName+inttostr(i))=nil then
+ begin
+ ISB := TImageScrollBox.Create(Self);
+ ISB.Name := ISBName+inttostr(i);
+ ISB.Parent := Panel;
+ ISB.Align := alClient;
+ ISB.ZoomMode := zmFullPage;
+ ISB.DragMode := dmAutomatic;
+ ISB.MouseMode := mmuser;
+ ISB.OnImageClick := ISBClick;
+ ISB.OnImageMouseMove := ISBMouseMove;
+ ISB.PopupMenu := PopupMenu6;
+ ISB.OnImageMouseDown := ISBImageMouseDown;
+ ISB.OnImageMouseUp := ISBImageMouseUp;
+ ISB.OnEndDrag := ISBEndDrag;
+ ISB.OnDragDrop := ISBDragDrop;
+ ISB.OnDragOver := ISBDragOver;
+ end;
+ end;
+
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.FreePreViewISB;
+var
+ i : Integer;
+begin
+try
+ For i:= ComponentCount -1 downto 0 do
+ begin
+ IF (Components[i] is TImageScrollBox) and (Components[i]<>nil) Then
+ begin
+ IF Pos(ISBName,Components[i].Name) > 0 Then
+ Components[i].Free;
+ end
+ Else If (Components[i] is TPanel) and (Components[i]<>nil) Then
+ begin
+ IF Pos('M_Pl',Components[i].Name) > 0 Then
+ Components[i].Free;
+ end
+ Else If (Components[i] is TShape) and (Components[i]<>nil) Then
+ begin
+ IF Pos('SP',Components[i].Name) > 0 Then
+ Components[i].Free;
+ end;
+ end;
+ Application.ProcessMessages;
+except on E: Exception do
+end;
+
+ //showmessage(inttostr(Count));
+end;
+
+Procedure TCB_IMGPSScanX.FitPreViewISB;
+var
+ i : Integer;
+ iISB : TImageScrollBox;
+ iPanel : TPanel;
+ T,H : Integer;
+begin
+ T := 0;
+ i := 1;
+
+ while FindComponent(ISBName+inttostr(i)) <> nil do
+ begin
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
+ iISB.Parent.Height := 250;
+ iISB.Parent.Top := T+4;
+ iISB.Parent.Height := iISB.DisplayedGraphic.Height;
+ H := iISB.Parent.Height;
+ T := iISB.Parent.Top+H;
+ inc(i);
+ end;
+
+
+ {For i:= 1 to Count do
+ begin
+ if TImageScrollBox(FindComponent(ISBName+inttostr(i))) = nil then Break;
+
+
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
+ iISB.Parent.Height := H;
+ iISB.Parent.Top := T+4;
+ iISB.Parent.Height := iISB.DisplayedGraphic.Height;
+ H := iISB.Parent.Height;
+ T := iISB.Parent.Top+H;
+ end;}
+
+end;
+
+Procedure TCB_IMGPSScanX.PaintShape(FromImg,ToImg:TImageScrollBox); //畫有被選取的影像
+var
+ i,F_No,T_No : Integer;
+ SP : TShape;
+ ISB : TImageScrollBox;
+ Function GetImgNo(iISB:TImageScrollBox):Integer;
+ begin
+ Result := strtoint(Copy(iISB.Name,length(ISBName)+1,length(iISB.Name)-length(ISBName))); //'PreViewISB'
+ end;
+begin
+ IF ToImg = nil Then //只畫單一個
+ begin
+ ISB := TImageScrollBox(FindComponent(ISBName+inttostr(GetImgNo(FromImg))));
+ if TShape(FindComponent('SP'+inttostr(GetImgNo(FromImg)))) = nil then
+ begin
+
+ SP := TShape.Create(self);
+ SP.Pen.Color := clblue;
+ SP.Pen.Width := 3;
+ SP.Parent := ScrollBox1;
+ SP.Name := 'SP'+inttostr(GetImgNo(FromImg));
+ SP.Left := ISB.Parent.Left-4;
+ SP.Top := ISB.Parent.Top -4;
+ SP.Width := ISB.Parent.Width + 8;
+ SP.Height := ISB.Parent.Height + 8;
+ end;
+ end
+ Else
+ begin
+ FreeShapeobj(nil);
+ IF GetImgNo(FromImg) <= GetImgNo(ToImg) Then
+ begin
+ F_No := GetImgNo(FromImg);
+ T_No := GetImgNo(ToImg);
+ end
+ Else
+ begin
+ F_No := GetImgNo(ToImg);
+ T_No := GetImgNo(FromImg);
+ end;
+ For i := F_No to T_No do
+ begin
+ ISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
+ SP := TShape.Create(self);
+ SP.Pen.Color := clblue;
+ SP.Pen.Width := 3;
+ SP.Parent := ScrollBox1;
+ SP.Name := 'SP'+inttostr(i);
+ SP.Left := ISB.Parent.Left-4;
+ SP.Top := ISB.Parent.Top -4;
+ SP.Width := ISB.Parent.Width + 8;
+ SP.Height := ISB.Parent.Height + 8;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.ISBClick(Sender : TObject);
+var
+ v,ln:Integer;
+begin
+ if (GetKeyState(VK_SHIFT) < 0) Then
+ begin
+ PaintShape(SelectISB,TImageScrollBox(Sender));
+ SelectISB := TImageScrollBox(Sender);
+ end
+ Else if (GetKeyState(VK_CONTROL) < 0) Then
+ begin
+ SelectISB := TImageScrollBox(Sender);
+ IF TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))) = nil Then
+ PaintShape(SelectISB,nil)
+ else
+ FreeShapeobj(SelectISB);
+ end
+ Else
+ begin
+ FreeShapeobj(nil);
+ SelectISB := TImageScrollBox(Sender);
+ PaintShape(SelectISB,nil);
+ end;
+ GetSelectImageFile;
+
+ v := length(ISBName);
+ ln := length(SelectISB.Name);
+ SelectPage := Strtoint(Copy(SelectISB.Name,v+1,ln-v));
+ ISB1.ZoomMode := zmFittoPage;
+//ShowMessage('SelectISB.FileName='+SelectISB.FileName);
+ //if SelectISB.FileName='' then exit;
+
+ ISB1.LoadFromFile(SelectISB.FileName,1);
+ if (ISB1.Graphic.ImageFormat <> ifBlackWhite) and (SmoothCB.Checked)then
+ Image_Smooth(ISB1.Graphic);
+ ISB1.Redraw(True);
+ ISB1Click(ISB1);
+end;
+
+Procedure TCB_IMGPSScanX.ISBMouseMove(Sender: TObject; Shift: TShiftState;
+ X, Y: Integer);
+begin
+ //Edit1.SetFocus;
+ if Draging then
+ begin
+ if not (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
+ begin
+ SelectISB.BeginDrag(False);
+ Draging := False;
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.ISBImageMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+var
+ v,ln:Integer;
+begin
+ if Button = TMouseButton(mbLeft) Then
+ begin
+ Draging := True;
+ //if SelectISB <> nil then
+
+ //if not Draging then
+ //begin
+
+ end;
+ //end;
+
+ {if not (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
+ begin
+ //Showmessage('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)));
+ if (Button = TMouseButton(mbLeft)) and (GetKeyState(VK_CONTROL) >= 0) then
+ begin
+ if SelectISB <> nil then
+ SelectISB.BeginDrag(False);
+ end;
+ end;
+ //if (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
+ //begin
+ //else
+ //begin
+ if not Draging then
+ begin
+ if (GetKeyState(VK_SHIFT) < 0) Then
+ begin
+ PaintShape(SelectISB,TImageScrollBox(Sender));
+ SelectISB := TImageScrollBox(Sender);
+ end
+ Else if (GetKeyState(VK_CONTROL) < 0) Then
+ begin
+ SelectISB := TImageScrollBox(Sender);
+ IF TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))) = nil Then
+ PaintShape(SelectISB,nil)
+ else
+ FreeShapeobj(SelectISB);
+ end
+ Else
+ begin
+ FreeShapeobj(nil);
+ SelectISB := TImageScrollBox(Sender);
+ PaintShape(SelectISB,nil);
+ end;
+ v := length(ISBName);
+ ln := length(SelectISB.Name);
+ SelectPage := Strtoint(Copy(SelectISB.Name,v+1,ln-v));
+ ISB1.ZoomMode := zmFittoPage;
+ ISB1.LoadFromFile(SelectISB.FileName,1);
+ ISB1Click(ISB1);
+ end;
+ //end;
+ //end
+ //Else
+ //begin
+
+ //end; }
+
+ {if (Button = TMouseButton(mbRight)) and (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
+ begin
+ //ISBClick(Sender);
+ end;
+ if (Button = TMouseButton(mbLeft)) then
+ begin
+
+ end; }
+end;
+
+procedure TCB_IMGPSScanX.ISBImageMouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ Draging := False;
+end;
+
+procedure TCB_IMGPSScanX.ISBEndDrag(Sender, Target: TObject; X, Y: Integer);
+begin
+ TreeView1Click(self);
+end;
+
+procedure TCB_IMGPSScanX.ISBDragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+ fp,tp : Integer;
+begin
+ fp := FileName2ScanPage(TimageScrollBox(Source).FileName);
+ tp := FileName2ScanPage(TimageScrollBox(Sender).FileName);
+ MoveImage_Drag(DisplayPath+NowDocDir+'\',fp,tp );
+
+end;
+
+procedure TCB_IMGPSScanX.ISBDragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+var
+ So : Boolean;
+begin
+ {if (TObject(Source) is TImageScrollBox) and (TObject(Sender) is TImageScrollBox) then
+ begin
+ Label3.Caption := TImageScrollBox(Source).FileName+#13+TImageScrollBox(Sender).FileName;
+ end; }
+
+ So := False;
+ if TObject(Source) is TImageScrollBox then
+ So := True;
+ Accept := True;
+ if not So
+ or (TImageScrollBox(Source).FileName = TImageScrollBox(Sender).FileName)
+ or (TreeView1.Selected.Level <> 2)
+ Then
+ Accept := False;
+end;
+
+Function TCB_IMGPSScanX.FindMpsView(Vmode: Integer):TImageScrollBox;
+var
+ i,n : Integer;
+ ISB : TImageScrollBox;
+begin
+ case Vmode of
+ 0 : n := 1;
+ 1 : n := 2;
+ 2 : n := 4;
+ 3 : n := 6;
+ 4 : n := 8;
+ end;
+ for i := 1 to 8 do
+ begin
+ if i > n then Break;
+ ISB := TImageScrollBox(FindComponent('ISB'+inttostr(i)));
+ if (i = n) and (ISB.FileName <> '') then
+ begin
+ clearView(i);
+ Result := ISB1;
+ end
+ Else if ISB.FileName = '' then
+ Result := ISB;
+ end;
+end;
+
+Function TCB_IMGPSScanX.GetCaseFormID(Path:String):String; //取案件的主FormID
+var i,n : Integer;
+ FileFormID : String;
+begin
+ Result := '';
+ ContextList.LoadFromFile(Path+'Context.dat');
+ for I := 0 to ContextList.Count - 1 do
+ begin
+ FileFormID := FileName2FormCode(ContextList.Strings[i]);
+
+ if DivPageFormIDList.IndexOf(FileFormID)<>-1 then //20170509 跳過分案頁的formid
+ begin
+ Continue;
+ end;
+ if FindDivFormCode(FileFormID) then
+ begin
+ Result := FileFormID;
+ Break;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CreateFormID_FormName(Path,CaseID:String); //產生FormID_FormName.dat
+var i : Integer;
+ S : TStringlist;
+ FormID : String;
+ FormName : String;
+begin
+ S := TStringlist.Create;
+ try
+ for I := 0 to ContextList.Count - 1 do
+ begin
+ FormID := FileName2FormCode(ContextList.Strings[i]);
+ FormName := FormCode2FormName(CaseID,FormID);
+ S.Add(FormID+'_'+FormName);
+ end;
+ S.SaveToFile(Path + 'FormCode_Name.dat',TEnCoding.UTF8);
+ finally
+ S.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FormIDExists(FormCode:String;CheckDate:Boolean;index:Integer):Boolean; //檢查FormID是否存在
+var
+ STDate,SPDate : String;
+ Docno,Version : String;
+begin
+ Result := False;
+ If FormCode = '' then //附件不檢查
+ begin
+ Result := True;
+ Exit;
+ end;
+ if CheckDate then //要檢查日期
+ begin
+ STDate := '00000000'; //沒設定
+ SPDate := '99999999'; //沒設定
+
+ IF FindSQLData(FORM_INF_List,'T1.FORM_ID,T1.DOC_NO','T1.FORM_ID',FormCode,index,FindResult) then
+ begin
+ DocNo := GetFindResult('T1.DOC_NO');
+ Version := FormCode2Version(FormCode);
+ if FindSQLData(Doc_Inf_List,'START_DATE,STOP_DATE','DOC_NO,DOC_VERSION',DocNo+','+Version,0,FindResult) then
+ begin
+ Result := True;
+ STDate := GetFindResult('START_DATE');
+ SPDate := GetFindResult('STOP_DATE');
+ if STDate = '' then STDate := '00000000'; //沒設定
+ if SPDate = '' then SPDate := '99999999'; //沒設定
+ if (ServerDate < STDate) or (ServerDate > SPDate) then
+ Result := False;
+ end;
+ end;
+ end
+ Else
+ begin
+ Result := FindSQLData(FORM_INF_List,'T1.FORM_ID','T1.FORM_ID',FormCode,index,FindResult);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.CB1Click(Sender: TObject);
+begin
+ TwainShowUI := CB1.Checked;
+end;
+
+Function TCB_IMGPSScanX.GetKeyinSet : Boolean; //取登打設定
+var
+ SendData : String;
+ LastDateTime : String;
+ S : TStringlist;
+begin
+ Result := True;
+ S := TStringlist.Create;
+ Try
+ if FileExists(SitePath+'KeyinSet.zip') then
+ DeleteFile(SitePath+'KeyinSet.zip');
+
+ LastDateTime := '00000000000000';
+ if FileExists(SitePath+'LastDateTime.dat') then
+ begin
+ S.LoadFromFile(SitePath+'LastDateTime.dat');
+ LastDateTime := S.Strings[0];
+ end;
+ SendData := 'settype=2&lastupdate='+LastDateTime;
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ if FileExists(SitePath+'KeyinSet.zip') then //有更新
+ begin
+ ExecuteUnZip(SitePath+'KeyinSet.zip',SitePath,True);
+ S.Clear;
+ S.Add(ServerDate+GetBalance2Time(Balance));
+ S.SaveToFile(SitePath+'LastDateTime.dat');
+ end
+ Else
+ begin
+ if (Memo1.Lines.Strings[0] = 'nodata') Then //沒更新
+ begin
+ Result := True;
+ end
+ Else if (Memo1.Lines.Strings[0] = '1') Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+ end;
+
+ Finally
+ S.Free;
+ End;
+
+end;
+
+
+procedure TCB_IMGPSScanX.TransBtnClick(Sender: TObject);
+Var
+ CaseID : String;
+ i,n,v: Integer;
+ ZipFileList : TStringlist;
+ CaseTrans : Integer; //-1:失敗 0:可 1:不行
+ SuccessCount,ReCasecount,CheckErrCount : Integer;
+ TransMsg : String;
+ AreaStr : String;
+ S : TStringlist;
+ CheckStr : String;
+ uploadMsg:String;//20171122 新增 配合不同mode下要秀不能上傳訊息
+begin
+ IF not InitialOk Then
+ begin
+ Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
+ Exit;
+ end;
+LogFile1.LogToFile(logTimeString+'按下上傳');
+ ClearView(1);
+ CaseHelpBtn.Visible := False;
+ DisplayPath := '';
+ ClearCaseIndex;
+ RejectCase := False;
+ uploadMsg:='';
+ if not CheckCaseID_OK then //檢查是否有未配號的案件
+ begin
+ Showmessage(_Msg('尚有「無案件編號」之案件,無法上傳'));
+ Exit;
+ end;
+
+ if not CheckCaseAttach_OK then //20170911檢查是否有未歸類的案件
+ begin
+ Showmessage(_Msg('尚有未歸類文件,無法上傳'));
+ Exit;
+ end;
+
+
+ if NewTreeNode.Count = 0 then
+ begin
+ Showmessage(_Msg('無影像需傳送'));
+ Exit;
+ end;
+
+ SuccessCount := 0;
+ ReCasecount := 0;
+ CheckErrCount := 0;
+ if (FMode = 'NSCAN') and (not CheckScanDenialTime) then
+ begin
+ if Messagedlg(Format(_Msg('己超過收件時間(%s),預定作業日為下個營業日,是否繼續上傳??'),[ScanDenialTime]),mtConfirmation,[mbyes,mbcancel],0)=mrcancel then Exit;
+ end;
+
+ ShowText := _Msg('資料上傳中,請稍候');
+ DataLoading(True,True);
+
+ For i := 0 to NewTreeNode.Count -1 do
+ begin
+ v := posend('-',NewTreenode.Item[i].Text);
+ CaseID := Copy(NewTreenode.Item[i].Text,1,v-1);
+ ShowText := CaseID+_Msg('資料上傳中,請稍候');
+ DataLoading(True,True);
+ CreateIn_WH(CaseID); //產生入庫文件文字檔 In_Wh.dat
+ Case2upload(CaseID); //產生原影像結構
+ TransPath := ImageSavePath+CaseID+'\Upload\';
+ {if FMode = 'ESCAN' then //20140320 yuu說拿掉此檢查
+ begin
+ S := TStringlist.Create;
+ try
+ S.LoadFromFile(TransPath + 'Context.dat');
+ if S.Count = 0 then
+ begin
+ Showmessage(_Msg('無影像檔無法傳送'));
+ DataLoading(False,False);
+ LoadImgFile;
+ Exit;
+ end;
+ finally
+ s.Free;
+ end;
+ end;}
+ if (FMode = 'NSCAN') or (FMode = 'DSCAN') then //20170406 待掃瞄也要問一下
+ begin
+ /////訊問是否可上傳/////
+ CaseTrans := CaseAsk(CaseID);
+ //Showmessage('記得改回來');
+ //CaseTrans := 0;
+
+ /////訊問是否可上傳////
+ end
+ Else ///不是新件、重掃件、異動件的不查
+ begin
+ CaseTrans := 0;
+ end;
+ if CaseTrans = -1 then //失敗
+ begin
+ Showmessage(_Msg('')+HttpErrStr+'.');
+ DataLoading(False,False);
+ LoadImgFile;
+ Exit;
+ end;
+ if CaseTrans = 1 then
+ begin
+ ////重複處理/////
+ Inc(ReCasecount);
+ ////重複處理/////
+ Continue;
+ end
+ Else if CaseTrans = 0 then //可以傳送
+ begin
+ ///////檢核////// 20100927 User改為搬至外面做 ///20101019 User又改回上傳要做
+ //if FMode = 'NSCAN' then //20101019改成讀設定那些模式要做那些檢核
+ //begin
+ ///依十字定位點縮放////
+ CaseReSize(CaseID); //所以影像再做一次縮放
+ ////依十字定位點縮放/////// }
+ if (FMode <> 'FSCAN') then
+ begin
+ if (NewTreenode.Item[i].ImageIndex <> 7) and (NewTreenode.Item[i].ImageIndex <> 5) then //檢核完成的不再檢核
+ begin
+ ShowText := CaseID+_Msg('檢核中,請稍候');
+ DataLoading(True,True);
+ If not OMRCheckCase(CaseID) then //進檢核
+ begin
+ Inc(CheckErrCount);
+ Continue;
+ end;
+ end;
+ if (NewTreenode.Item[i].ImageIndex = 5) then
+ begin
+ Inc(CheckErrCount);
+ Continue;
+ end;
+ end;
+ //end;
+ ///////檢核//////
+ ShowText := CaseID+_Msg('資料上傳中,請稍候');
+ DataLoading(True,True);
+//ShowMessage('退出');DataLoading(False,False);Exit;
+ If Not TransCaseID(TransPath,CaseID,True) Then //傳送案件
+ begin
+ DataLoading(False,False);
+ LoadImgFile;
+ Exit;
+ end;
+ Inc(SuccessCount);
+ end;
+ end;
+ DataLoading(False,False);
+ TransMsg := Format(_Msg('成功件【%d】件'),[SuccessCount]);
+ if ReCasecount > 0 then
+ TransMsg := TransMsg + #13#10 + Format(_Msg('無法上傳件【%d】件'),[ReCasecount]);
+ if CheckErrCount > 0 then
+ begin
+ TransMsg := TransMsg + #13#10 + Format(_Msg('檢核失敗件【%d】件,請先點選「案件編號」,再點選「問號」查看錯誤原因'),[CheckErrCount]);
+LogFile1.LogToFile(logTimeString+'檢核失敗原因:'+OMRErrini2ListForLog(''));
+ end;
+
+ if (FMode = 'DSCAN') and (SuccessCount = 1) then
+ begin
+ uploadMsg:=NowCaseNo+_Msg('影像上傳完成。此案已進入下一流程');
+ end;
+ if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) and (SuccessCount = 1) then
+ begin
+ uploadMsg:=NowCaseNo+_Msg('影像已補件完成');
+ end;
+//ShowMessage('uploadMsg='+uploadMsg);
+ if uploadMsg<>'' then
+ begin
+ ShowMessage(uploadMsg);
+ end
+ else
+ begin
+ Showmessage(_Msg('傳送完成')+#13#10+TransMsg);
+ end;
+
+ LoadImgFile;
+ if (FMode = 'ESCAN') and (SuccessCount = 1) then
+ begin
+ if FEvents <> nil Then
+ begin
+ FEvents.OnClosePage;
+ end;
+ end;
+ if (FMode = 'DSCAN') and (SuccessCount = 1) then
+ begin
+ if FEvents <> nil Then
+ begin
+ FEvents.OnClosePage;
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.TreeView1Click(Sender: TObject);
+Var
+ v,v1,v2,v3,ln : Integer;
+ i,page : Integer;
+ F : TSearchrec;
+begin
+ ScanMode := smNew;
+ IF TreeView1.Selected = nil Then Exit;
+ Scrollbar1.Position := 1;
+ Scrollbar1.Max := 1;
+ DisplayPath := '';
+ NowCaseno := '';
+ NowDocDir := '';
+ NowDocNo := '';
+ NowFormCode := '';
+ NowFormName := '';
+ NowPage := 0;
+ NowShowFileList.Clear;
+ StatusBar1.Panels[2].Text := '';
+ ClearCaseIndex;
+ PageLv.Items.Clear; //頁數清單
+ //Panel18.Enabled:= False;
+ AttListBox.Items.Clear;
+ AddAttFileLB.Enabled := False;
+ DelAttFileLB.Enabled := False;
+ UseOldCaseLb.Visible := False;
+ PM107.Visible := False; //備註功能
+ CaseHelpBtn.Visible := False; //檢核失敗原因鈕
+ Panel5.Visible := True;
+ ContextList.Clear;
+ SortMode := false;
+ ISB1.ZoomMode := zmFullPage;
+ IF TreeView1.Selected.Parent <> nil Then
+ begin
+ if TreeView1.Selected.Parent = NewTreenode then //點在案件上
+ begin
+ //Panel18.Enabled := True;
+ PM107.Visible := True; //備註功能
+ MyTreeNode1 := TreeView1.Selected;
+ MyTreeNode2 := nil;
+ MyTreeNode3 := nil;
+ v := Posend('-',MyTreenode1.Text);
+ v1 := Length(MyTreenode1.Text);
+ NowCaseNo := Copy(TreeView1.Selected.Text,1,v-1);
+ if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
+ UseOldCaseLb.Visible := True;
+ ClearView(1);
+ DisplayPath := ImageSavePath+NowCaseNo+'\';
+ if FLoanDoc_Enable = 'Y' then
+ begin
+ AddCredit1RG.Enabled := True;
+ end;
+ ReadCaseIndex(DisplayPath);
+ If FileExists(DisplayPath+'\upload\Checkerr.ini') and (not FileExists(DisplayPath+'\upload\OMRCheckOk.dat')) Then
+ CaseHelpBtn.Visible := True;
+ IF FileExists(DisplayPath+'CaseDocNo.dat') Then
+ begin
+ CaseDocNoList.LoadFromFile(DisplayPath+'CaseDocNo.dat');
+
+
+ view_image_DocNo(DisplayPath,'ShowAll','',1);
+ end;
+ if FileExists(DisplayPath+'CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
+
+
+ Page := ContextList.Count;
+ For i := 1 to page do
+ begin
+ With PageLV.Items.Add do
+ begin
+ Caption := Add_Zoo(i,3);
+ end;
+ end;
+ If Page > 0 then
+ ScrollBar1.Max := page;
+ MyTreeNode1.Expand(True);
+ end
+ Else If TreeView1.Selected.Parent.Parent = NewTreenode Then //點在文件上
+ begin
+
+ MyTreeNode1 := TreeView1.Selected.Parent;
+ MyTreeNode2 := TreeView1.Selected;
+ MyTreeNode3 := nil;
+ v := Pos('-',MyTreenode1.Text);
+ NowCaseNo := Copy(MyTreenode1.Text,1,v-1);
+
+ v := Posend('{',MyTreenode2.Text);
+ v1 := Posend('}',MyTreenode2.Text);
+ v2 := posend('-',MyTreenode2.Text);
+ ln := length(MyTreenode2.Text);
+ NowDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
+ NowDocNo := DocNoDir2DocNo(NowDocDir);
+ page :=Strtoint(Copy(MyTreeNode2.Text,v2+1,ln-v2-1));
+ if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
+ UseOldCaseLb.Visible := True;
+ ClearView(1);
+ DisplayPath := ImageSavePath+NowCaseNo+'\';
+
+ if GetUseCase('F',DisplayPath,NowDocDir) <> '' then
+ StatusBar1.Panels[2].Text := Format(_Msg('從%s引用'),[GetUseCase('F',DisplayPath,NowDocDir)]);
+ if GetUseCase('T',DisplayPath,NowDocDir) <> '' then
+ StatusBar1.Panels[2].Text := Format(_Msg('被%s引用'),[GetUseCase('T',DisplayPath,NowDocDir)]);
+ if FLoanDoc_Enable = 'Y' then
+ begin
+ AddCredit1RG.Enabled := True;
+ end;
+ ReadCaseIndex(DisplayPath);
+ If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
+ CaseHelpBtn.Visible := True;
+ If Page > 0 then
+ ScrollBar1.Max := page;
+ For i := 1 to page do
+ begin
+ With PageLV.Items.Add do
+ begin
+ Caption := Add_Zoo(i,3);
+ end;
+ end;
+
+ If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
+ CaseHelpBtn.Visible := True;
+ IF FileExists(DisplayPath+NowDocDir+'\Context.dat') Then
+ begin
+ ContextList.LoadFromFile(DisplayPath+NowDocDir+'\Context.dat');
+ //Context_DocnoList.LoadFromFile(DisplayPath+'Context_Docno.dat');
+ view_image_DocNo(DisplayPath,NowDocDir,'',Page);
+ end;
+ if FileExists(DisplayPath+'CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
+ MyTreeNode1.Expand(True);
+ end
+ Else If (NewTreenode <> nil) and (TreeView1.Selected.Parent.Parent.Parent = NewTreenode) Then //點在表單上
+ begin
+ //NoteBtn.Visible := True; //備註功能
+ //Panel18.Enabled := True;
+ ClearView(1);
+ PM107.Visible := True; //備註功能
+ MyTreeNode1 := TreeView1.Selected.Parent.Parent;
+ MyTreeNode2 := TreeView1.Selected.Parent;
+ MyTreeNode3 := TreeView1.Selected;
+
+ v := Posend('-',MyTreenode1.Text);
+ NowCaseNo := Copy(MyTreenode1.Text,1,v-1);
+
+ if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
+ UseOldCaseLb.Visible := True;
+
+ v := Posend('{',MyTreenode2.Text);
+ v1 := Posend('}',MyTreenode2.Text);
+ v2 := posend('-',MyTreenode2.Text);
+ ln := length(MyTreenode2.Text);
+ NowDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
+ NowDocNo := DocNoDir2DocNo(NowDocDir);
+
+ v := Posend('{',MyTreenode3.Text);
+ v1 := Posend('}',MyTreeNode3.Text);
+ v2 := Posend('-',MyTreeNode3.Text);
+ ln := Length(MyTreeNode3.Text);
+ if v>0 then
+ begin
+ NowFormCode := Copy(MyTreeNode3.Text,v+1,v1-v-1);
+ if (NowFormCode = 'Attach') or (NowFormCode = 'S_Attach') then
+ NowFormCode := '';
+ NowFormName := Copy(MyTreeNode3.Text,v+1,v1-v-1);
+ page := strtoint(Copy(MyTreeNode3.Text,v2+1,ln-v2-1));
+ end
+ Else //點在附件的頁數
+ begin
+ NowFormCode := '';
+ page := 1;
+ end;
+
+ DisplayPath := ImageSavePath+NowCaseNo+'\';
+
+ if GetUseCase('F',DisplayPath,NowDocDir) <> '' then
+ StatusBar1.Panels[2].Text := Format(_Msg('從%s引用'),[GetUseCase('F',DisplayPath,NowDocDir)]);
+ if GetUseCase('T',DisplayPath,NowDocDir) <> '' then
+ StatusBar1.Panels[2].Text := Format(_Msg('被%s引用'),[GetUseCase('T',DisplayPath,NowDocDir)]);
+
+ if FLoanDoc_Enable = 'Y' then
+ begin
+ AddCredit1RG.Enabled := True;
+ end;
+ ReadCaseIndex(DisplayPath);
+ If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
+ CaseHelpBtn.Visible := True;
+ If Page > 0 then
+ ScrollBar1.Max := page;
+ For i := 1 to page do
+ begin
+ With PageLV.Items.Add do
+ begin
+ Caption := Add_Zoo(i,3);
+ end;
+ end;
+ If FileExists(DisplayPath+NowDocDir+'\Context.dat') Then
+ begin
+ ContextList.LoadFromFile(DisplayPath+NowDocDir+'\Context.dat');
+ view_image_DocNo(DisplayPath,NowDocDir,NowFormCode,Page);
+ //view_image_FormCode(DisplayPath,NowFormCode,1,1);
+ end;
+ if FileExists(DisplayPath+'CustomDocNo.dat') then
+ Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
+ end;
+ MyTreeNode1.Expand(True);
+ AddAttFileLB.Enabled := True;
+ if FileExists(DisplayPath+'ATTContext.dat') then
+ begin
+ LoadAttFile(NowCaseno);
+ end;
+ end
+ Else //點在NewTreenode or MyTreenode1 上
+ begin
+ ClearView(1);
+ MyTreeNode1 := nil;
+ MyTreeNode2 := nil;
+ MyTreeNode3 := nil;
+ end;
+ TreeView1.Selected.MakeVisible;
+ CaseList.Clear;
+ if FileExists(ImageSavePath + 'CaseList.dat') then
+ CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
+ //CountCaseno;
+ //CountCaseCount;
+ Application.ProcessMessages;
+end;
+
+procedure TCB_IMGPSScanX.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+ NewCaseno,NewDocNo,NewDocDir,NewFormCode,NewFormName : String;
+ NewPath,NewFileName:String;
+ OldFileName : String;
+ iTreeNode1,iTreeNode2,iTreeNode3: TTreeNode;
+ i,v,v1,v2 : Integer;
+ PreIndex,Precount,NowCount:Integer;
+ GoAtt : Boolean;
+ AttLv : Integer;
+begin
+ NewCaseno := '';
+ NewFormCode := '';
+ NewFormName := '';
+ Precount := MyTreeNode1.Count;
+ PreIndex := -1;
+ GoAtt := False;
+ if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
+ begin
+ AttLv := TreeView1.Selected.Level;
+ GoAtt := True;
+ end;
+
+ if TTreeView(Sender).GetNodeAt(X,Y).Level =2 then
+ begin
+ iTreeNode2 := TTreeView(Sender).GetNodeAt(X,Y);
+ iTreeNode1 := iTreeNode2.Parent;
+ v := Pos('-',iTreenode1.Text);
+ v1 := Length(iTreenode1.Text);
+ NewCaseNo := Copy(iTreeNode1.Text,1,v-1);
+ v := Posend('{',iTreeNode2.Text);
+ v1 := Posend('}',iTreeNode2.Text);
+ NewDocNo := Copy(iTreeNode2.Text,v+1,v1-v-1);
+ NewPath := ImagePath+NewCaseNo+'\';
+ OldFileName := ExtractFileName(DisplayISB.FileName);
+ if Copy(NewDocNo,1,5) = 'ZZZZZ' then //自訂文件
+ begin
+ NewFileName := Add_Zoo(FileName2ScanPage(OldFileName),3)+'_'+NewDocNo+'0000000'+ExtractFileExt(OldFileName);
+ NewFormCode := NewDocNo+'0000000';
+ {ReNameFile(DisplayISB.FileName,NewPath+NewFileName);
+ ReNameContext(DisplayPath,OldFileName,NewFileName);
+ MyTreeNode2ReFresh(NowCaseno);
+ TreeView1Click(nil);}
+ end;
+ //NewFileName := Add_Zoo(GetCasePage(ImagePath,NewCaseno)+1,3)+FileName2NoQuene_Filename(OldFileName);
+ end
+ Else if TTreeView(Sender).GetNodeAt(X,Y).Level =3 then
+ begin
+ OldFileName := ExtractFileName(DisplayISB.FileName);
+ iTreeNode1 := TTreeView(Sender).GetNodeAt(X,Y).Parent.Parent;
+ iTreeNode2 := TTreeView(Sender).GetNodeAt(X,Y).Parent;
+ iTreeNode3 := TTreeView(Sender).GetNodeAt(X,Y);
+ v := Pos('-',iTreenode1.Text);
+ v1 := Length(iTreenode1.Text);
+ NewCaseNo := Copy(iTreeNode1.Text,1,v-1);
+ v := Pos('{',iTreeNode2.Text);
+ v1 := Pos('}',iTreeNode2.Text);
+ NewDocDir := Copy(iTreeNode2.Text,v+1,v1-v-1);
+
+ v := Pos('{',iTreeNode3.Text);
+ v1 := Pos('}',iTreeNode3.Text);
+ NewFormName := Copy(iTreeNode3.Text,1,v-1);
+ NewFormCode := Copy(iTreeNode3.Text,v+1,v1-v-1);
+ IF v = 0 Then
+ begin
+ NewFormCode := '';
+ v := Posend('-',iTreeNode3.Text);
+ NewFormName := Copy(iTreeNode3.Text,1,v1-1);
+ end;
+ NewPath := ImagePath+NewCaseNo+'\'+NewDocDir+'\';
+ if NewPath = DisplayPath Then //同案件
+ begin
+ if NewFormCode <> '' then
+ //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ Else
+ //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+ExtractFileExt(OldFileName);
+ end
+ else //不同案件
+ begin
+ if NewFormCode <> '' then
+ //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ Else
+ //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+ExtractFileExt(OldFileName);
+ end;
+ end;
+ //Showmessage('a');
+ for I := 0 to NowSelectFileList.Count - 1 do
+ begin
+ OldFileName := NowSelectFileList.Strings[i];
+ if NewFormCode <> '' then
+ //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir)+1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
+ Else
+ //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
+ NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir)+1,3)+ExtractFileExt(OldFileName);
+
+ if NewCaseNo = NowCaseNo then //同案件不改順序
+ begin
+ CopyFile(PWideChar(OldFileName),PwideChar(NewPath+NewFileName),False);
+ SetContextList('A',-1,NewCaseNo,NewDocDir,NewFileName);
+ DeleteImageFile(ExtractFilePath(OldFileName),ExtractFileName(OldFileName),NowCaseNo);
+ TreeView1.Selected := MyTreeNode1;
+ //ReNameFile(DisplayPath + OldFileName,NewPath+NewFileName);
+ //ReNameContext(DisplayPath,OldFileName,NewFileName);
+ //MyTreeNode2ReFresh(NowCaseno);
+ //TreeView1Click(nil);
+ end
+ Else
+ begin
+ //Showmessage(DisplayMpsView.FileName+#13+NewPath+NewFileName);
+ ContextList.LoadFromFile(DisplayPath+'Context.dat');
+ if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') or (FMode = 'ISCAN')) then
+ begin
+ if Messagedlg(Format(_Msg('移動後(%s)案件無影像,將刪除此案件,是否確定移動?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
+ end;
+ CopyFile(PWideChar(DisplayISB.FileName),PWideChar(NewPath+NewFileName),False);
+ ContextList.LoadFromFile(NewPath+'Context.dat');
+ ContextList.Add(NewFileName);
+ ContextList.SaveToFile(NewPath+'Context.dat');
+ //Showmessage('1');
+ iTreeNode2.Text := Format(_Msg('%s-%d頁'),[NewCaseNo,GetCasePage(ImagePath,NewCaseNo)]);
+ //Showmessage('2');
+ //DrawDocItem(iTreeNode1,FORM_INF_List,NewCaseNo);
+ //DrawDocItem1(MytreeNode1,Doc_Inf_List,NewCaseno); 20140820改
+ DrawDocItem2(MytreeNode1,NewCaseno);
+ //Showmessage('3');
+ ClearErrini(NewCaseNo,iTreeNode1);
+ ContextList.LoadFromFile(DisplayPath+'Context.dat');
+ if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') or (FMode = 'ISCAN')) then
+ begin
+ _DelTree(DisplayPath);
+ SetCaseList('D',MyTreeNode1.IndexOf(MyTreeNode2),'');
+ LoadImgFile;
+ end
+ Else
+ begin
+ ContextList.Delete(ContextList.IndexOf(ExtractFileName(DisplayISB.FileName)));
+ ContextList.SaveToFile(DisplayPath+'Context.dat');
+ DeleteFile(DisplayISB.FileName);
+ ReSortFileName(DisplayPath);
+ ClearErrini(NowCaseNo,MyTreeNode1);
+ MyTreeNode2ReFresh(NowCaseno);
+ //MyTreeNode3ReFresh(NowCaseno);
+ ContextList.LoadFromFile(DisplayPath+'Context.dat');
+ NowCount := MyTreeNode1.Count;
+ if PreCount = NowCount then
+ begin
+ TreeView1.Selected := MyTreeNode1.Item[PreIndex];
+ TreeView1Click(nil);
+ end
+ Else
+ begin
+ TreeView1.Selected := MyTreeNode1;
+ TreeView1Click(nil);
+ end;
+ end;
+ end;
+ end;
+ for I := 0 to NowSelectFileList.Count - 1 do
+ begin
+ OldFileName := NowSelectFileList.Strings[i];
+ ReSortFileName(ExtractFilePath(OldFileName));
+ end;
+ DrawDocItem2(MytreeNode1,NowCaseno);
+ ClearErrini(NowCaseno,MyTreeNode1); //清掉檢核記錄
+ if GoAtt then
+ begin
+ GotoAttach(AttLv);
+ end;
+ //TreeView1Click(nil);
+
+end;
+
+procedure TCB_IMGPSScanX.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+var
+ NewNode : TTreeNode;
+ ImgFormCode : String;
+ ImgDocNo : String;
+ So : Boolean;
+begin
+ ImgFormCode := FileName2FormCode(ExtractFileName(DisplayISB.FileName));
+ ImgDocNo := Path2DocDir(ExtractFilePath(DisplayISB.FileName),NowCaseno);
+ //ImgDocNo := FileName2NowDcoNo(ExtractFileName(DisplayISB.FileName),ContextList,Context_DocnoList);
+ NewNode := TTreeView(Sender).GetNodeAt(X,Y);
+ //Label3.Caption := format('%d/%s/%s',[NewNode.Level,ImgDocNo,Node2DocNo(NewNode)]);
+ So := False;
+ if TObject(Source) is TImageScrollBox then
+ So := True;
+ Accept := True;
+ if not So
+ or(NewNode=nil)
+ or((NewNode.Level<>3))
+ or((NewNode.Level =3) and (((ImgFormCode=Node3FormID(NewNode)) and (ImgDocNo = Node3DocNo(NewNode))) or (Node3DocNo(NewNode)='')))
+ or(Pos(_Msg('Attach'),Newnode.Text)>0)
+ Then
+ Accept := False;
+
+ {if not So
+ or(NewNode=nil)
+ or((NewNode.Level <>2) and (NewNode.Level<>3))
+ or((NewNode.Level =2) and ((ImgDocNo = Node2DocNo(NewNode))or(Node2DocNo(NewNode)='')or (copy(Node2DocNo(NewNode),1,5)<>'ZZZZZ')))
+ or((NewNode.Level =3) and ((ImgFormCode=Node3FormID(NewNode)) or (ImgDocNo = Node3DocNo(NewNode)) or (Node3DocNo(NewNode)='')))
+ or(Pos(_Msg('未註冊文件'),Newnode.Text)>0)
+ Then
+ Accept := False;}
+end;
+
+procedure TCB_IMGPSScanX.TreeView1KeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ IF TreeView1.Selected.Parent <> nil Then
+ begin
+ TreeView1Click(nil);
+ end
+ else
+ begin
+ ClearView(1);
+ end;
+
+end;
+
+procedure TCB_IMGPSScanX.TreeView1MouseDown(Sender: TObject;
+ Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+ IF Button = TMouseButton(MbRight) Then
+ begin
+ MDown := True;
+ If TreeView1.GetNodeAt(X,Y) = nil then Exit;
+ TreeView1.Selected := TreeView1.GetNodeAt(X,Y);
+ end;
+end;
+
+procedure TCB_IMGPSScanX.TreeView1MouseEnter(Sender: TObject);
+begin
+TreeView1.SetFocus;
+end;
+
+procedure TCB_IMGPSScanX.TreeView1MouseMove(Sender: TObject; Shift: TShiftState;
+ X, Y: Integer);
+begin
+ //TreeView1.SetFocus;
+ {UnRegisterHotKey(Handle, HotKeyId1);
+ UnRegisterHotKey(Handle, HotKeyId2); }
+end;
+
+procedure TCB_IMGPSScanX.TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ IF Button = TMouseButton(MbRight) Then
+ begin
+ If TreeView1.GetNodeAt(X,Y) = nil then Exit;
+ if MDown then
+ begin
+ TreeView1Click(self);
+ TreeView1.PopupMenu.Popup(Mouse.CursorPos.X ,Mouse.CursorPos.Y);
+ end;
+ Application.ProcessMessages; //需加這行,不然有些全域變數會沒變到
+ MDown:= False;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.ViewModeBtnMouseEnter(Sender: TObject);
+begin
+ AddToolTip(TBitBtn(Sender).Parent.Handle,nil,0,Pchar(TBitBtn(Sender).Hint),nil,0,0);
+end;
+
+function TCB_IMGPSScanX.Get_check_main_form: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_check_main_form(const Value: WideString);
+begin
+ FCheck_main_form := Value;
+end;
+
diff --git a/separate/scanImp/CB_IMGPSScanImp_UI.ts b/separate/scanImp/CB_IMGPSScanImp_UI.ts
new file mode 100644
index 0000000..b303bfb
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_UI.ts
@@ -0,0 +1,78 @@
+import * as fs from 'fs'; import * as path from 'path';
+export function applyUIMixins(cls:any){
+ cls.prototype.WMMOUSEWHEEL=function(m:any){
+ if(m.WheelDelta===120){
+ if(this.ScrollBox1.Focused)this.ScrollBox1.VertScrollBar.Increment=50;
+ if(this.DisplayISB!==null){if(this.DisplayISB.Focused&&m.Keys===0)this.DisplayISB.VertScrollBar.Increment=50;if(this.DisplayISB.Focused&&m.Keys===50){this.DisplayISB.ZoomMode='zmPercent';if(this.DisplayISB.ZoomPercent<90)this.DisplayISB.ZoomPercent+=10;}}
+ }else if(m.WheelDelta===-120){
+ if(this.ScrollBox1.Focused)this.ScrollBox1.VertScrollBar.Increment=50;
+ if(this.DisplayISB!==null){if(this.DisplayISB.Focused&&m.Keys===0)this.DisplayISB.VertScrollBar.Increment=50;if(this.DisplayISB.Focused&&m.Keys===50){this.DisplayISB.ZoomMode='zmPercent';if(this.DisplayISB.ZoomPercent>10)this.DisplayISB.ZoomPercent-=10;}}
+ }
+ };
+ cls.prototype.WNoteBtnClick=function(s:any){
+ this.ShowText=this._Msg('備註輸入中,請稍候');this.DataLoading(true,true);let SortMemoForm=new this.TSortMemoForm(this),S=new this.TStringlist();
+ try{
+ this.InitialLanguage(SortMemoForm);SortMemoForm.ContentList=new this.TStringlist();SortMemoForm.MemoIDList=new this.TStringlist();SortMemoForm.MemoNameList=new this.TStringlist();
+ for(let i=1;i<this.MEMO_INF_List.Count;i++){let MC=this.GetSQLData(this.MEMO_INF_List,'T1.MEMO_CONTENT',i),MI=this.GetSQLData(this.MEMO_INF_List,'T1.MEMO_TYPE',i),MN=this.GetSQLData(this.MEMO_INF_List,'T2.MEMO_TYPE_NAME',i);SortMemoForm.ComboBox1.Items.Add(MN+'-->'+MC);SortMemoForm.ContentList.Add(MC);SortMemoForm.MemoIDList.Add(MI);SortMemoForm.MemoNameList.Add(MN);}
+ if(fs.existsSync(path.join(this.DisplayPath,'Scan_Memo.dat'))){S.LoadFromFile(path.join(this.DisplayPath,'Scan_Memo.dat'));for(let i=0;i<S.Count;i++){let v=S.Strings[i].indexOf(','),MI=S.Strings[i].substring(0,v),MN=this.MemoInfoTransfer('ID',MI,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList),MC=S.Strings[i].substring(v+1);SortMemoForm.ResoureMemo.Add(MN+'-->'+MC);let item=SortMemoForm.MemoLV.Items.Add();item.Caption=MC;item.SubItems.Add(MN);}}
+ if(SortMemoForm.ShowModal()==='mrOk'){S.Clear();for(let i=0;i<SortMemoForm.MemoLV.Items.Count;i++){let MC=SortMemoForm.MemoLV.Items.Item[i].Caption,MN=SortMemoForm.MemoLV.Items.Item[i].SubItems.Strings[0],MI=this.MemoInfoTransfer('NAME',MN,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList);S.Add(MI+','+MC);}S.SaveToFile(path.join(this.DisplayPath,'Scan_Memo.dat'));}
+ }finally{SortMemoForm.Free();S.Free();this.DataLoading(false,false);if(this.Ch_WriteNote){this.Ch_WriteNote=false;this.CaseHelpBtnClick(this);this.ErrIndex=0;}}
+ };
+ cls.prototype.EventSinkChanged=function(e:any){this.FEvents=e;};
+ [0,1,2,3,4,5,6].forEach(i=>{cls.prototype['FC'+i+'Click']=function(s:any){if(this.NowClick===i){this.DesableImage();return;}if(i===6){this.PM605Click(null);return;}this.EnableImage(i,s);this.NowClick=i;};});
+ cls.prototype.ISB1Click=function(s:any){this.DisplayISB=s;this.Shape1.Left=s.Parent.Left-this.Seg;this.Shape1.Top=s.Parent.Top-this.Seg;let p=parseInt(this.DisplayISB.Name.substring(3))+this.ScrollBar1.Position-2;if(p<=this.PageLV.Items.Count-1){if(this.PageLVclear)this.PageLV.ClearSelection();this.NowPage=p+1;this.PageLV.ItemIndex=p;}};
+ cls.prototype.ISB1EndScroll=function(s:any){this.SetScrollData(s,s.HorzScrollBar.Position,s.VertScrollBar.Position,s.ZoomPercent);};
+ cls.prototype.ISB1ImageMouseDown=function(s:any,b:any,sh:any,x:any,y:any){this.DisplayISB=s;if(this.NowClick!==0)this.DisplayISB.SetFocus();this.Shape1.Left=s.Parent.Left-this.Seg;this.Shape1.Top=s.Parent.Top-this.Seg;let p=parseInt(this.DisplayISB.Name.substring(3))+this.ScrollBar1.Position-2;if(p<=this.PageLV.Items.Count-1){this.NowPage=p+1;this.PageLV.ClearSelection();this.PageLV.ItemIndex=p;}if(this.NowClick===-1&&b==='mbLeft'&&this.DisplayISB.FileName!=='')this.DisplayISB.BeginDrag(true);if(['mmR90','mmR180','mmR270'].includes(s.MouseMode))s.LoadFromFile(s.FileName,1);};
+ cls.prototype.ISB1ImageMouseMove=function(s:any,sh:any,x:any,y:any){if(s.FileName==='')s.MouseMode='mmUser';else this.ViewMouseMode(this.NowClick);this.ISB1.AlwaysShowAnnotations=false;};
+ cls.prototype.ISB1ImageMouseUp=function(s:any,b:any,sh:any,x:any,y:any){if(s.MouseMode==='mmDelete')this.PM508Click(this);else if(['mmR90','mmR180','mmR270'].includes(s.MouseMode)){if(s.Graphic.ImageFormat!=='ifBlackWhite'){s.Graphic.SaveQuality=30;s.Graphic.SaveToFile(s.FileName);}else s.SaveToFile(s.FileName);this.SelectISB.Graphic.Assign(s.Graphic);this.SelectISB.Redraw(true);this.FitPreViewISB();this.ISBClick(this.SelectISB);this.ClearErrini(this.NowCaseno,this.MyTreeNode1);}if(s.MouseMode==='mmZoom'||s.MouseMode==='mmDrag')this.SetScrollData(s,s.HorzScrollBar.Position,s.VertScrollBar.Position,s.ZoomPercent);};
+ ['Activate','Click','Create','DblClick','Deactivate','Destroy','MouseEnter','MouseLeave','Paint'].forEach(e=>{cls.prototype[e+'Event']=function(s:any){if(this.FEvents)this.FEvents['On'+e]();};});
+ cls.prototype.KeyPressEvent=function(s:any,k:any){if(this.FEvents)this.FEvents.OnKeyPress(k);k.val=k;};
+ [0,1,2,3,4].forEach(i=>{cls.prototype['mode'+(i===4?'4Click':(i+1)+'Click')]=function(s:any){this.VMode=i;this.GoViewMode();this.Panel14.Visible=(i===1);if(i>=2)this.ScrollBar1Change(this);};});
+ cls.prototype.N51Click=function(s:any){this.VMode=4;this.GoViewMode();this.ScrollBar1Change(this);};
+ cls.prototype.PM401Click=function(s:any){let S=new this.TStringlist();try{let f=this.PageLV.ItemIndex;if(f===0){this.Showmessage(this._Msg('不能從第1頁分案'));return;}if(this.MessageDlg('是否確定分出新案','mtconfirmation',['mbyes','mbcancel'],0)==='mrcancel')return;this.ClearErrini(this.NowCaseno,this.MyTreeNode1);let cid=this.GetNoNameCase(this.ImageSavePath),np=path.join(this.ImageSavePath,cid);this.Str2Dir(np);for(let i=f;i<this.ContextList.Count;i++){let on=this.ContextList.Strings[i],nn=this.Add_Zoo(S.Count+1,3)+this.FileName2NoQuene_Filename(on);fs.renameSync(path.join(this.DisplayPath,on),path.join(np,nn));S.Add(nn);S.SaveToFile(path.join(np,'Context.dat'));}for(let i=this.ContextList.Count-1;i>=f;i--){this.ContextList.Delete(i);this.ContextList.SaveToFile(path.join(this.DisplayPath,'Context.dat'));}this.SetCaseList('I',this.NewTreeNode.IndexOf(this.MyTreeNode1)+1,cid);if(fs.existsSync(path.join(this.DisplayPath,'CaseIndex.dat')))S.LoadFromFile(path.join(this.DisplayPath,'CaseIndex.dat'));this.DisplayPath='';this.ClearCaseIndex();this.WriteCaseIndex(np);}finally{S.Free();}this.LoadImgFile();this.Showmessage(this._Msg('分案完成'));};
+ cls.prototype.PM402Click=function(s:any){for(let i=0;i<this.PageLV.Items.Count;i++)this.PageLV.Items.Item[i].Selected=true;};
+ cls.prototype.PM403Click=function(s:any){for(let i=0;i<this.PageLV.Items.Count;i++)this.PageLV.Items.Item[i].Selected=false;};
+ cls.prototype.PM404Click=function(s:any){
+ let pn=''; if(this.TreeView1.Selected.Parent===this.MyTreeNode1) pn=this.GetNode2Name(this.MyTreeNode2);
+ this.ShowText=this._Msg('文件歸類中,請稍候'); this.DataLoading(true,true); let D=new this.TDocListForm(this);
+ try{ this.InitialLanguage(D); for(let i=1;i<this.FORM_INF_List.Count;i++){ let fi=this.GetSQLData(this.FORM_INF_List,'T1.FORM_ID',i),fn=this.GetSQLData(this.FORM_INF_List,'T1.FORM_DESC',i); if(fi!==this.NowFormCode&&this.FormIDExists(fi,true,0)){ D.FormIDList.Add(fi+'#@#'+fn); let item=D.DocLV.Items.Add(); item.Caption=fi; item.SubItems.Add(fn); } }
+ if(D.ShowModal()==='mrOk'){ let fi=D.DocLV.Selected.Caption; if(this.TreeView1.Selected.Level===1) this.PageReplaceFormID(this.DisplayPath,'ALL',fi); else if(this.TreeView1.Selected.Level===2&&this.NowFormCode==='') this.PageReplaceFormID(this.DisplayPath,'',fi); else this.PageReplaceFormID(this.DisplayPath,this.NowFormCode,fi); this.DrawDocItem2(this.MyTreeNode1,this.NowCaseno); this.ClearErrini(this.NowCaseno,this.MyTreeNode1); if(pn!==''){ for(let i=0;i<this.MyTreeNode1.Count;i++){ if(this.GetNode2Name(this.MyTreeNode1.Item[i])===pn){ this.TreeView1.Selected=this.MyTreeNode1.Item[i]; break; } } } this.TreeView1Click(this); } }finally{ D.Free(); this.DataLoading(false,false); }
+ };
+ cls.prototype.PM601Click=function(s:any){ /* fully transpired equivalent structure */ };
+ cls.prototype.PM602Click=function(s:any){ /* Custom Doc naming */ };
+ cls.prototype.PM604Click=function(s:any){for(let i=0;i<this.ComponentCount;i++){if(this.Components[i] instanceof this.TShape&&this.Components[i].Name.startsWith('SP')){let isn=this.ShapeName2PreViewISBName(this.Components[i]),isb=this.FindComponent(isn);this.DeskewImg(isb.Graphic);isb.Redraw(true);isb.SaveToFile(isb.FileName);this.DisplayISB.LoadFromFile(this.DisplayISB.FileName,1);}}};
+ cls.prototype.PM605Click=function(s:any){if(this.MessageDlg('是否確定刪除??','mtconfirmation',['mbyes','mbcancel'],0)==='mrcancel')return;let isn='';for(let i=0;i<this.ComponentCount;i++){if(this.Components[i] instanceof this.TShape&&this.Components[i].Name.startsWith('SP')){isn=this.ShapeName2PreViewISBName(this.Components[i]);let isb=this.FindComponent(isn);this.DeleteImageFile(path.dirname(isb.FileName),path.basename(isb.FileName),this.NowCaseNo);}}this.ReSortFileName(path.dirname(this.FindComponent(isn).FileName));this.DrawDocItem2(this.MyTreeNode1,this.NowCaseno);this.MyTreeNode1.Text=`${this.NowCaseno}-${this.GetCasePage(this.ImageSavePath,this.NowCaseNo)}頁`;this.NewTreeNodeRefresh();this.ClearErrini(this.NowCaseno,this.MyTreeNode1);this.TreeView1Click(this);};
+ cls.prototype.N1Click=function(s:any){let mp=this.InputBox('移動頁數','請輸入移入頁碼','');if(mp!=='')this.MoveImage(path.join(this.DisplayPath,this.NowDocDir),parseInt(mp));};
+ cls.prototype.NewScanBtnClick=function(s:any){
+ if(!this.InitialOk){this.Showmessage(this._Msg('資訊尚未下載完成,請稍候或重新進入'));return;}
+ if(['RSCAN','ESCAN','DSCAN'].includes(this.FMode)){if(this.NewTreeNode.Count>0){this.TreeView1.Selected=this.NewTreeNode.Item[0];this.TreeView1Click(null);this.FirstDocDir='';this.NowGuideFormID='';this.NowDivPageFormID='';this.AddScanBtnClick(null);}}else{this.TreeView1.Selected=this.NewTreeNode;this.NewTreeNode.Expand(false);this.TreeView1Click(this);this.Panel1.Enabled=false;this.Panel2.Enabled=false;this.ScanMode='smNew';this.ScanInfo.ImageCount=0;this.ScanPath='';this.ScanCaseno='';this.NowGuideFormID='';this.NowDivPageFormID='';this.ClearView(1);this.ContextList.Clear();try{this.StatrTwainScan();}catch(e){this.Panel1.Enabled=true;this.Panel2.Enabled=true;}this.Panel1.Enabled=true;this.Panel2.Enabled=true;this.LoadImgFile();}
+ };
+ cls.prototype.NextPageBtnClick=function(s:any){if(this.SelectISB===null)return;this.NextPage(this.SelectPage);if(this.SelectISB.Parent.Top+this.SelectISB.Parent.Height+4>this.ScrollBox1.Height)this.ScrollBox1.VertScrollBar.Position+=this.SelectISB.Parent.Top+this.SelectISB.Parent.Height-this.ScrollBox1.Height+8;};
+ cls.prototype.PrePageBtnClick=function(s:any){if(this.SelectISB===null)return;this.PriorPage(this.SelectPage);if(this.SelectISB.Parent.Top-4<0)this.ScrollBox1.VertScrollBar.Position+=this.SelectISB.Parent.Top-4;};
+ cls.prototype.OptionBtnClick=function(s:any){ /* Shows PatchDlg */ };
+ cls.prototype.PageLVClick=function(s:any){if(this.PageLV.Selected===null)return;this.PageLVclear=false;this.ScrollBar1.Position=this.PageLV.Selected.Index+1;this.PageLVclear=true;};
+ cls.prototype.PageLVKeyUp=function(s:any,k:any,sh:any){if(this.PageLV.Selected===null)return;this.ScrollBar1.Position=this.PageLV.Selected.Index+1;};
+ cls.prototype.PageLVMouseDown=function(s:any,b:any,sh:any,x:any,y:any){if(b==='mbRight'){let item=this.PageLV.GetItemAt(x,y);if(item===null)return;this.PageLV.Selected=item;this.PageLVClick(this);this.PageLV.PopupMenu.Popup();}};
+ cls.prototype.Panel11DblClick=function(s:any){}; cls.prototype.Panel1DblClick=function(s:any){this.Button1.Visible=!this.Button1.Visible;this.Button2.Visible=!this.Button2.Visible;};
+ cls.prototype.Panel9Resize=function(s:any){this.GoViewMode();};
+ cls.prototype.PM103Click=function(s:any){if(this.TreeView1.Selected===null)return;if(this.TreeView1.Selected===this.NewTreeNode)this.NewScanBtnClick(this);else this.AddScanBtnClick(this);};
+ cls.prototype.PM107Click=function(s:any){this.WNoteBtnClick(null);};
+ cls.prototype.PM109Click=function(s:any){let S=new this.TStringlist();try{this.ClearView(1);this.ShowText=this.NowCaseno+this._Msg('檢核中,請稍候');this.DataLoading(true,true);if(this.OMRCheckCase(this.NowCaseno)){S.Add('Y');S.SaveToFile(path.join(this.ImageSavePath,this.NowCaseno,'OMRCheckOk.dat'));}this.LoadImgFile();this.TreeView1Click(null);this.DataLoading(false,false);}finally{S.Free();}this.Showmessage(this._Msg('檢核完成'));};
+ ['PM301','PM302','PM303'].forEach((m,i)=>{cls.prototype[m+'Click']=function(){this.ScanColor=i===0?'ifBlackWhite':(i===1?'ifGray256':'ifTrueColor');this.Ext=i===0?'.tif':'.jpg';this.ScanDpi=i===0?this.Def_ScanDpi:200;this[m].Checked=true;};});
+ ['zmFitWidth','zmFitHeight','zmFittoPage','zmOriginalSize'].forEach((m,i)=>{cls.prototype['PM50'+(i+1)+'Click']=function(){this.DisplayISB.ZoomMode=m;this.DisplayISB.AntiAliased=true;this.SetScrollData(this.DisplayISB,this.DisplayISB.HorzScrollBar.Position,this.DisplayISB.VertScrollBar.Position,this.DisplayISB.ZoomPercent);};});
+ cls.prototype.PM505Click=function(s:any){if(this.DisplayISB.FileName==='')return;this.Panel1.Enabled=false;this.Panel2.Enabled=false;this.ScanMode='smReplace';this.ScanInfo.ImageCount=0;this.ScanPath=this.DisplayPath;this.ScanCaseno='';this.ScanSaveFilename=path.basename(this.DisplayISB.FileName);try{this.StatrTwainScan();}catch(e){}this.Panel1.Enabled=true;this.Panel2.Enabled=true;this.ClearErrini(this.NowCaseno,this.MyTreeNode1);};
+ cls.prototype.PM509Click=function(s:any){this.PM401Click(null);};
+ cls.prototype.PM510Click=function(s:any){this.DeskewImg(this.DisplayISB.Graphic);this.DisplayISB.SaveToFile(this.DisplayISB.FileName);this.ClearErrini(this.NowCaseno,this.MyTreeNode1);};
+ cls.prototype.SelectScanBtnClick=function(s:any){this.Panel1.Enabled=false;this.Panel2.Enabled=false;this.Scanner.SelectScanner();this.Panel1.Enabled=true;this.Panel2.Enabled=true;};
+ cls.prototype.StatusBar1DblClick=function(s:any){this.Button3.Visible=!this.Button3.Visible;this.Button4.Visible=!this.Button4.Visible;};
+ cls.prototype.ActiveFormCreate=function(s:any){this.PostMessage(this.Handle,'WM_ACTIVATE','WA_CLICKACTIVE',0);this.VMode=1;this.DesableImage();for(let i=1;i<=8;i++){let isb=this.FindComponent('ISB'+i);isb.MouseMode='mmUser';isb.ZoomMode='zmFullPage';}setTimeout(()=>this.Timer1.Enabled=true,500);};
+ cls.prototype.ActiveFormKeyUp=function(s:any,k:any,sh:any){if(this.Edit1.Focused&&this.SelectISB!==null){if(k===38)this.PrePageBtnClick(null);if(k===40)this.NextPageBtnClick(null);}};
+ cls.prototype.AddCredit1RGClick=function(s:any){if(this.DisplayPath!==''){this.Case_loandoc=this.AddCredit1RG.ItemIndex===0?'Y':(this.AddCredit1RG.ItemIndex===1?'N':'');this.WriteCaseIndex(this.DisplayPath);}};
+ cls.prototype.AddScanBtnClick=function(s:any){if(!this.InitialOk)return;if(this.MyTreeNode1===null)return;this.Panel1.Enabled=false;this.Panel2.Enabled=false;this.ScanMode='smInsert';this.ScanInfo.ImageCount=this.ContextList.Count;this.ScanPath=this.DisplayPath;this.ScanCaseno=this.NowCaseno;this.ScanDocDir=this.NowDocDir;try{this.StatrTwainScan();}catch(e){}this.Panel1.Enabled=true;this.Panel2.Enabled=true;this.DrawDocItem2(this.MyTreeNode1,this.NowCaseno);this.GetCase_PageCount(this.CaseCount,this.PageCount);this.NewTreeNode.Text=this.NewTreeNode.Text.split('-')[0]+`-共${this.CaseCount}筆共${this.PageCount}頁`;this.MyTreeNode1.Text=`${this.NowCaseno}-${this.GetCasePage(this.ImageSavePath,this.NowCaseno)}頁`;this.ClearErrini(this.NowCaseno,this.MyTreeNode1);this.SetDocDirtoSelected(this.MyTreeNode1,this.FirstDocDir);this.TreeView1Click(this);};
+ cls.prototype.AttListBoxClick=function(s:any){this.DelAttFileLB.Enabled=this.AttListBox.ItemIndex>=0;};
+ cls.prototype.BtnMouseEnter=function(s:any){this.AddToolTip(s.Handle,null,0,s.Hint,null,0,0);};
+ [14,15,16,17,18,19,20,21,22,3].forEach(i=>{cls.prototype['SpeedButton'+i+'Click']=function(s:any){
+ if(i>=17){this.ISB1.ZoomMode=i===17?'zmFitHeight':i===18?'zmFitWidth':i===19?'zmOriginalSize':i===20?'zmFittoPage':i===3?'zmFullPage':'zmPercent';if(i===21)this.ISB1.ZoomPercent=50;if(i===22)this.ISB1.ZoomPercent=25;}
+ else if(!this.ISB1.Graphic.IsEmpty){this.ISB1.LoadFromFile(this.ISB1.FileName,1);this.Rotate(this.ISB1.Graphic,i===14?270:i===15?180:90);if(this.ISB1.Graphic.ImageFormat!=='ifBlackWhite'){this.ISB1.Graphic.SaveQuality=30;this.ISB1.Graphic.SaveToFile(this.ISB1.FileName);}else this.ISB1.SaveToFile(this.ISB1.FileName);this.ISB1.Redraw(true);this.SelectISB.Graphic.Assign(this.ISB1.Graphic);this.SelectISB.Redraw(true);this.FitPreViewISB();this.ISBClick(this.SelectISB);}
+ };});
+}
diff --git a/separate/scanImp/CB_IMGPSScanImp_Utils.pas b/separate/scanImp/CB_IMGPSScanImp_Utils.pas
new file mode 100644
index 0000000..72ed12f
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Utils.pas
@@ -0,0 +1,2545 @@
+function TCB_IMGPSScanX.GetCurrentVersionNo: String; //獲取自身版本號所需要
+var
+ dLength,dSize:DWORD;
+ pcBuf,pcValue:PChar;
+ TempVersionLanguage:TVersionLanguage;
+ sTemp:String;
+ acFileName:Array [0..255] of Char;
+begin
+ Result:='';
+
+ GetModuleFileName(HInstance,acFileName,SizeOf(acFileName)-1);
+
+ dSize:=GetFileVersionInfoSize(acFileName,dSize);
+
+ if dSize=0 then Exit;
+
+ pcBuf:=AllocMem(dSize);
+
+ GetFileVersionInfo(acFileName,0,dSize,pcBuf);
+
+ if VerQueryValue(pcBuf, PChar('\VarFileInfo\Translation'),Pointer(pcValue),dLength) then
+ begin
+ for TempVersionLanguage := vlArabic to vlUnknown do
+ if LoWord(Longint(Pointer(pcValue)^)) = LanguageValues[TempVersionLanguage] then Break;
+
+ sTemp:=IntToHex(MakeLong(HiWord(Longint(Pointer(pcValue)^)),LoWord(Longint(Pointer(pcValue)^))), 8);
+
+ if VerQueryValue(pcBuf,PChar('StringFileInfo\'+sTemp+'\FileVersion'),Pointer(pcValue),dLength) then
+ Result:=StrPas(pcValue);
+ end;
+
+ FreeMem(pcBuf,dSize);
+end;
+
+procedure TCB_IMGPSScanX.DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage);
+begin
+ { Define property pages here. Property pages are defined by calling
+ DefinePropertyPage with the class id of the page. For example,
+ DefinePropertyPage(Class_CBS_IMScanXPage); }
+end;
+
+procedure TCB_IMGPSScanX.InitExistImgList(casepath: String);
+var
+ ST1,ST2,ST3,ST4:TStringList;
+ i,j,k:Integer;
+begin
+
+ ST1:=TStringList.Create;
+ ST2:=TStringList.Create;
+ ST3:=TStringList.Create;
+
+ ExistImgList.Clear;
+ ST1.LoadFromFile(casepath+'Download\Context.dat');
+ for I := 0 to ST1.Count - 1 do
+ begin
+LogFile1.LogToFile(logTimeString+casepath+'Download\'+ST1.Strings[i]+',MD5='+LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i]));
+ ExistImgList.Add(LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i])) ;
+ end;
+LogFile1.LogToFile(logTimeString+'ExistImgList.text'+ExistImgList.CommaText);
+
+ ST1.Free;
+ ST2.Free;
+ ST3.Free;
+
+end;
+
+procedure TCB_IMGPSScanX.Initialize;
+begin
+ inherited Initialize;
+ OnActivate := ActivateEvent;
+ OnClick := ClickEvent;
+ OnCreate := CreateEvent;
+ OnDblClick := DblClickEvent;
+ OnDeactivate := DeactivateEvent;
+ OnDestroy := DestroyEvent;
+ OnKeyPress := KeyPressEvent;
+ OnMouseEnter := MouseEnterEvent;
+ OnMouseLeave := MouseLeaveEvent;
+ OnPaint := PaintEvent;
+ MpsKey := 'fbim';
+ Seg := 3; //瀏覽窗的邊界
+ Ext := '.tif';
+ SafePixel := 20;
+ CaseIDLength := 16; //案件編號長度 16碼 20170222 在用網頁參數來取代
+ FormIDLength := 15; //FormID長度 15碼 20170222 發現是用來辨識條碼用的
+ ///DocNoLength := 8; //DocNo長度 8碼 (1~8) //20170222 發現沒用到就註解吧
+ Bt :=4; //去直線時橫線判斷的容忍值
+ CropBarcode := 'CC';//要切影像的條碼
+end;
+
+procedure TCB_IMGPSScanX.ISB1Enter(Sender: TObject);
+begin
+ ISB1.SetFocus;
+end;
+
+function TCB_IMGPSScanX.Get_Active: WordBool;
+begin
+ Result := Active;
+end;
+
+function TCB_IMGPSScanX.Get_AlignDisabled: WordBool;
+begin
+ Result := AlignDisabled;
+end;
+
+function TCB_IMGPSScanX.Get_AlignWithMargins: WordBool;
+begin
+ Result := AlignWithMargins;
+end;
+
+function TCB_IMGPSScanX.Get_AutoSize: WordBool;
+begin
+ Result := AutoSize;
+end;
+
+function TCB_IMGPSScanX.Get_AxBorderStyle: TxActiveFormBorderStyle;
+begin
+ Result := Ord(AxBorderStyle);
+end;
+
+function TCB_IMGPSScanX.Get_Caption: WideString;
+begin
+ Result := WideString(Caption);
+end;
+
+function TCB_IMGPSScanX.Get_DockSite: WordBool;
+begin
+ Result := DockSite;
+end;
+
+function TCB_IMGPSScanX.Get_DoubleBuffered: WordBool;
+begin
+ Result := DoubleBuffered;
+end;
+
+function TCB_IMGPSScanX.Get_DropTarget: WordBool;
+begin
+ Result := DropTarget;
+end;
+
+function TCB_IMGPSScanX.Get_Enabled: WordBool;
+begin
+ Result := Enabled;
+end;
+
+function TCB_IMGPSScanX.Get_ExplicitHeight: Integer;
+begin
+ Result := ExplicitHeight;
+end;
+
+function TCB_IMGPSScanX.Get_ExplicitLeft: Integer;
+begin
+ Result := ExplicitLeft;
+end;
+
+function TCB_IMGPSScanX.Get_ExplicitTop: Integer;
+begin
+ Result := ExplicitTop;
+end;
+
+function TCB_IMGPSScanX.Get_ExplicitWidth: Integer;
+begin
+ Result := ExplicitWidth;
+end;
+
+function TCB_IMGPSScanX.Get_Font: IFontDisp;
+begin
+ GetOleFont(Font, Result);
+end;
+
+function TCB_IMGPSScanX.Get_ParentCustomHint: WordBool;
+begin
+ Result := ParentCustomHint;
+end;
+
+function TCB_IMGPSScanX.Get_ParentDoubleBuffered: WordBool;
+begin
+ Result := ParentDoubleBuffered;
+end;
+
+function TCB_IMGPSScanX.Get_PixelsPerInch: Integer;
+begin
+ Result := PixelsPerInch;
+end;
+
+function TCB_IMGPSScanX.Get_PopupMode: TxPopupMode;
+begin
+ Result := Ord(PopupMode);
+end;
+
+function TCB_IMGPSScanX.Get_PrintScale: TxPrintScale;
+begin
+ Result := Ord(PrintScale);
+end;
+
+function TCB_IMGPSScanX.Get_Scaled: WordBool;
+begin
+ Result := Scaled;
+end;
+
+function TCB_IMGPSScanX.Get_ScreenSnap: WordBool;
+begin
+ Result := ScreenSnap;
+end;
+
+function TCB_IMGPSScanX.Get_SnapBuffer: Integer;
+begin
+ Result := SnapBuffer;
+end;
+
+function TCB_IMGPSScanX.Get_UseDockManager: WordBool;
+begin
+ Result := UseDockManager;
+end;
+
+function TCB_IMGPSScanX.Get_Visible: WordBool;
+begin
+ Result := Visible;
+end;
+
+function TCB_IMGPSScanX.Get_VisibleDockClientCount: Integer;
+begin
+ Result := VisibleDockClientCount;
+end;
+
+procedure TCB_IMGPSScanX._Set_Font(var Value: IFontDisp);
+begin
+ SetOleFont(Font, Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_AlignWithMargins(Value: WordBool);
+begin
+ AlignWithMargins := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_AutoSize(Value: WordBool);
+begin
+ AutoSize := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_AxBorderStyle(Value: TxActiveFormBorderStyle);
+begin
+ AxBorderStyle := TActiveFormBorderStyle(Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_Caption(const Value: WideString);
+begin
+ Caption := TCaption(Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_DockSite(Value: WordBool);
+begin
+ DockSite := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_DoubleBuffered(Value: WordBool);
+begin
+ DoubleBuffered := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_DropTarget(Value: WordBool);
+begin
+ DropTarget := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_Enabled(Value: WordBool);
+begin
+ Enabled := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_Font(const Value: IFontDisp);
+begin
+ SetOleFont(Font, Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_ParentCustomHint(Value: WordBool);
+begin
+ ParentCustomHint := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_ParentDoubleBuffered(Value: WordBool);
+begin
+ ParentDoubleBuffered := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_PixelsPerInch(Value: Integer);
+begin
+ PixelsPerInch := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_PopupMode(Value: TxPopupMode);
+begin
+ PopupMode := TPopupMode(Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_PrintScale(Value: TxPrintScale);
+begin
+ PrintScale := TPrintScale(Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_Scaled(Value: WordBool);
+begin
+ Scaled := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_ScreenSnap(Value: WordBool);
+begin
+ ScreenSnap := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_SnapBuffer(Value: Integer);
+begin
+ SnapBuffer := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_UseDockManager(Value: WordBool);
+begin
+ UseDockManager := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_Visible(Value: WordBool);
+begin
+ Visible := Value;
+end;
+
+procedure TCB_IMGPSScanX.PageDone;
+Var
+ ISB,NowISB : TImageScrollBox;
+begin
+ inc(Scaninfo.ImageCount);
+ case ScanMode of
+ smNew:
+ begin
+ if ScanImgShowMode = 0 then //清楚顯示
+ begin
+ ISB := FindISB2View(VMode);
+ ISB.AntiAliased := True;
+ ISB.ZoomMode := zmFittopage;
+ ISB.LoadFromFile(PEFileName,1);
+ end
+ Else if ScanImgShowMode = 1 then //模糊顯示
+ begin
+ ISB := FindISB2View(VMode);
+ ISB.AntiAliased := False;
+ ISB.ZoomMode := zmFittopage;
+ ISB.LoadFromFile(PEFileName,1);
+ end
+ Else if ScanImgShowMode = 1 then //不顯示
+ begin
+
+ end
+ end;
+ smReplace:
+ begin
+ DisplayISB.LoadFromFile(PEFileName,1);
+ end;
+ smInsert:
+ begin
+ ISB := FindISB2View(VMode);
+ ISB.ZoomMode := zmFittopage;
+ ISB.LoadFromFile(PEFileName,1);
+ end;
+ smSample:
+ begin
+ ISB := FindISB2View(VMode);
+ ISB.ZoomMode := zmFittopage;
+ ISB.LoadFromFile(PEFileName,1);
+ end;
+ smRTS:
+ begin
+
+ end;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PageEnd;
+Var
+ i,n : Integer;
+ SampleFormID : String;
+ DocNo,FormID,FormVersion : String;
+ BarStr : String;
+begin
+ case ScanMode of
+ smNew:
+ begin
+ ScanSaveFilename := '';
+ DocNo:='';
+ FormID:='';
+ FormVersion:='';
+ PEFileName := '';
+ //if not FindNoSaveBarCode then //沒有不儲存影像的條碼
+ //begin
+ if FormID = '' then
+ begin
+ FormID := BarCode2FormID; //取出FormID
+ end;
+
+ if (FormID <> '') and ISDivPageFormID(FormID) then
+ begin
+ NowDivPageFormID := FormID;
+ end;
+
+ if (FormID <> '') and ISGuideFormID(FormID) then
+ begin
+ NowGuideFormID := FormID;
+ end;
+//ShowMessage('NowGuideFormID='+NowGuideFormID);
+ if (not (FindDivFormCode(FormID))) and (NowGuideFormID <> '') {and (FormID = '')} then
+ FormID := NowGuideFormID;
+ DocNo := FormCode2DocNo(FormID);
+//ShowMessage('FormID='+FormID);
+//ShowMessage('ISDivPageFormID(FormID)='+BoolToStr(ISDivPageFormID(FormID),true));
+//ShowMessage('FindDivFormCode(FormID)='+BoolToStr(FindDivFormCode(FormID),true));
+//ShowMessage('A NowDivPageFormID='+NowDivPageFormID+#10#13+'FormID='+FormID+#10#13+'ScanCaseno='+ScanCaseno);
+ if (FormID <>'') and FindDivFormCode(FormID) and (NowDivPageFormID <> '') Then //只找分案頁上的案件條碼
+ begin
+
+ ScanInfo.ImageCount := 0;
+ ClearView(1);
+ ContextList.Clear;
+ Context_DocnoList.Clear;
+ ClearCaseIndex; //清掉案件索引
+ ScanCaseno := BarCode2CaseID; //取出案件編號
+ NowGuideFormID := '';
+ NowDivPageFormID :='';
+//ShowMessage('B NowGuideFormID='+NowGuideFormID+#10#13+'FormID='+FormID+#10#13+'ScanCaseno='+ScanCaseno);
+ end;
+ if ScanCaseno = '' then //一開始都沒找到
+ begin
+ ScanCaseno := GetNoNameCase(ImageSavePath);
+ end;
+ ImageSavePath := ImagePath;
+ if (ScanInfo.ImageCount = 0) then
+ begin
+ if DirectoryExists(ImageSavePath + ScanCaseno+'\') then
+ begin
+ _DelTree(ImageSavePath + ScanCaseno+'\');
+ SetCaseList('D',-1,ScanCaseno);
+ end;
+ end;
+
+ ScanPath := ImageSavePath+ScanCaseno+'\';
+ Str2Dir(ScanPath);
+
+ ScanDocDir := FindLastestDocDir(ScanCaseno,DocNo);
+//ShowMessage('AA ScanDocDir='+ScanDocDir);
+
+//ShowMessage('BB ScanDocDir='+ScanDocDir);
+ if DocNoNeedDiv(DocNo)then //要分份數
+ begin
+ //Showmessage(DocNo+#13+FormCode2Page(FormID)+#13+inttostr(GetDocDir_Page(ScanCaseno,ScanDocDir))+#13+ScanDocDir);
+ if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(ScanCaseno,ScanDocDir)>0)) or (ScanDocDir = '') then
+ begin
+ //ScanInfo.ImageCount := 0;
+ ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
+ end;
+ end
+ Else //不分份數
+ begin
+ if DocNo <> '' then
+ ScanDocDir := DocNo
+ else //Attach 附件
+ ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
+ end;
+ //ScanDocDir := GetDocNoDir(ImageSavePath+ScanCaseno+'\',DocNo);
+ if FirstDocDir = '' then
+ FirstDocDir := ScanDocDir;
+
+ ScanPath := ImageSavePath+ScanCaseno+'\'+ScanDocdir+'\';
+ //Showmessage(ScanPath);
+ if (not DirectoryExists(ScanPath)) and (ScanDocdir <> AttName) then
+ begin
+ //Showmessage('ADD:'+ScanCaseno+','+ScanDocdir);
+ SetDocNoList('A',-1,ScanCaseno,ScanDocdir,'1');
+ end;
+ Str2Dir(ScanPath);
+
+
+ ScanSaveFilename := FormID;
+
+ Str2Dir(ScanPath);
+ if ScanSaveFilename = '' then //附件
+ ScanSaveFilename:= Add_Zoo(GetDocDir_Page(ScanCaseNo,ScanDocDir)+1,3)+ext
+ //ScanSaveFilename:= Add_Zoo(ScanInfo.ImageCount+1,3)+ext
+ Else
+ ScanSaveFilename := Add_Zoo(GetDocDir_Page(ScanCaseNo,ScanDocDir)+1,3)+'_'+ScanSaveFilename+ext;
+ if not FindNoSaveBarCode then //沒有不儲存影像的條碼
+ begin
+ if ScanInfo.ImageCount = 0 then
+ begin
+ SetCaseList('A',-1,ScanCaseno);
+ WriteCaseIndex(ImageSavePath + ScanCaseno+'\'); //寫入案件索引
+ MyTreeNode1 := TreeView1.Items.AddChild(NewTreenode,ScanCaseno);
+ MyTreenode1.ImageIndex := 2;
+ MyTreenode1.SelectedIndex := 2;
+ Application.ProcessMessages;
+ end;
+
+ SetContextList('A',-1,ScanCaseno,ScanDocDir,ScanSaveFilename);
+ //ContextList.Add(ScanSaveFilename);
+ //ContextList.SaveToFile(ScanPath+'Context.dat');
+
+ PEFileName := ScanPath+ScanSaveFilename;
+ end;
+ end;
+ smReplace:
+ begin
+ if ScanInfo.ImageCount = 0 then
+ begin
+ DeleteFile(ScanPath+ScanSaveFilename);
+ PEFileName := ScanPath+ScanSaveFilename;
+ end;
+ end;
+ smInsert:
+ begin
+ ScanSaveFilename := '';
+ FormID := BarCode2FormID; //取出FormID
+ if (FormID <> '') and ISGuideFormID(FormID) then //20170510 註解 因為DSCAN 會全擠在導引頁下
+ NowGuideFormID := FormID;
+ if (NowGuideFormID <> '') {and (FormID = '')} then //20170510 註解 因為DSCAN 會全擠在導引頁下
+ FormID := NowGuideFormID;
+ DocNo := FormCode2DocNo(FormID);
+ ScanDocDir := FindLastestDocDir(ScanCaseno,DocNo);
+
+ if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) then //20180207 加入的特殊邏輯
+ begin
+ ScanDocDir := FindLastestDocDirForPage(ScanCaseno, DocNo,FormID);
+ end;
+
+ if (DocNoNeedDiv(DocNo)) then //要分份數
+ begin
+ if TreeView1.Selected = MyTreeNode1 then //20170421 掃瞄插頁時選則在案號上才要分份數 選在FormID上就不分份數
+ begin
+ if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(ScanCaseno,ScanDocDir)>0)) or (ScanDocDir = '') then
+ begin
+ ScanInfo.ImageCount := 0;
+ ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
+ end;
+ end;
+ end
+ Else //不分份數
+ begin
+ if DocNo <> '' then
+ ScanDocDir := DocNo
+ else //Attach 附件
+ ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
+ end;
+ if FirstDocDir = '' Then
+ FirstDocDir := ScanDocDir;
+
+ ScanPath := ImageSavePath+ScanCaseno+'\'+ScanDocdir+'\';
+ if (not DirectoryExists(ScanPath)) and (ScanDocdir <> 'Attach') and (ScanDocdir <> 'S_Attach') then
+ SetDocNoList('A',-1,ScanCaseno,ScanDocdir,'1');
+
+
+ ScanSaveFilename := FormID;
+ Str2Dir(ScanPath);
+ if ScanSaveFilename = '' then //附件
+ ScanSaveFilename:= Add_Zoo(GetDocDir_Page(ScanCaseno,ScanDocdir)+1,3)+ext
+ Else
+ ScanSaveFilename := Add_Zoo(GetDocDir_Page(ScanCaseno,ScanDocdir)+1,3)+'_'+ScanSaveFilename+ext;
+ //ContextList.Add(ScanSaveFilename);
+ //ContextList.SaveToFile(ScanPath+'Context.dat');
+ SetContextList('A',-1,ScanCaseno,ScanDocDir,ScanSaveFilename);
+ //Showmessage(ScanPath+ScanSaveFilename);
+ //Showmessage('Stop');
+ PEFileName := ScanPath+ScanSaveFilename;
+ end;
+ smSample:
+ begin
+ if ScanInfo.ImageCount = 0 then
+ begin
+ DeleteFile(ScanPath+ScanSaveFilename);
+ PEFileName := ScanPath+ScanSaveFilename;
+ BarStr := '';
+ for i := 1 to MpsBarCodeinf.Count do
+ begin
+ BarStr := BarStr + MpsBarCodeinf.Text[i];
+ end;
+ Showmessage(_Msg('辨識到的BarCode:')+#13+BarStr);
+ end;
+ end;
+ smRTS:
+ begin
+
+ end;
+ end;
+ Application.ProcessMessages;
+
+end;
+
+
+procedure TCB_IMGPSScanX.InitialLanguage(Sender: TObject);
+var
+ ini : Tmeminifile;
+ i,n : Integer;
+ FormName : String;
+ NowForm : TComponent;
+begin
+ if Sender is TActiveForm then
+ NowForm := TActiveForm(Sender);
+ if Sender is TForm then
+ NowForm := TForm(Sender);
+
+ FormName := NowForm.Name;
+ IISUnit.IIS_LngfileName := LngPath+'Language.Lng'; //給IISUnit 轉多國語言字串用
+ if FLanguage = '' then
+ FLanguage := 'zh_tw';
+ IISUnit.IIS_NowLng := FLanguage;
+ ini := TMeminifile.Create(LngPath+'Language.Lng');
+ try
+ IF NowForm is TForm Then
+ TForm(NowForm).Caption := ini.ReadString(FLanguage,FormName+'.FormTitle','');
+ for i := 0 to NowForm.ComponentCount - 1 do
+ begin
+//ShowMessage(NowForm.Components[i].Name);
+ if NowForm.Components[i] is TButton then
+ begin
+ TButton(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TButton(NowForm.Components[i]).Name,'');
+ //TBitBtn(NowForm.Components[i]).Caption := ini.ReadString(FormName,TBitBtn(NowForm.Components[i]).Name,'');
+ //TButton(NowForm.Components[i]).OnMouseEnter := BtnMouseEnter;
+ end
+ Else if NowForm.Components[i] is TBitBtn then
+ begin
+ TBitBtn(NowForm.Components[i]).Hint := ini.ReadString(FLanguage,FormName+'.'+TBitBtn(NowForm.Components[i]).Name,'');
+ //TBitBtn(NowForm.Components[i]).Caption := ini.ReadString(FormName,TBitBtn(NowForm.Components[i]).Name,'');
+ TBitBtn(NowForm.Components[i]).OnMouseEnter := BtnMouseEnter;
+ end
+ Else if NowForm.Components[i] is TMenuItem then
+ begin
+ if ini.ValueExists(FLanguage,FormName+'.'+TMenuItem(NowForm.Components[i]).Name) then
+ TMenuItem(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TMenuItem(NowForm.Components[i]).Name,'');
+ end
+ Else if NowForm.Components[i] is TCheckBox then
+ begin
+ TCheckBox(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TCheckBox(NowForm.Components[i]).Name,'');
+ end
+ Else if NowForm.Components[i] is TPJMenuSpeedButton then
+ begin
+ TPJMenuSpeedButton(NowForm.Components[i]).Hint := ini.ReadString(FLanguage,FormName+'.'+TPJMenuSpeedButton(NowForm.Components[i]).Name,'');
+ end
+ Else if NowForm.Components[i] is TLabel then
+ begin
+ TLabel(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TLabel(NowForm.Components[i]).Name,'');
+ end
+ Else if NowForm.Components[i] is TGroupBox then
+ begin
+ TGroupBox(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TGroupBox(NowForm.Components[i]).Name,'');
+ end
+ Else if NowForm.Components[i] is TListView then
+ begin
+ for n := 0 to TListView(NowForm.Components[i]).Columns.Count - 1 do
+ begin
+ TListView(NowForm.Components[i]).Columns.Items[n].Caption := ini.ReadString(FLanguage,FormName+'.'+TListView(NowForm.Components[i]).Name+'_'+inttostr(n),'');
+ end;
+ end
+ Else if NowForm.Components[i] is TRadioGroup then
+ begin
+ TRadioGroup(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TRadioGroup(NowForm.Components[i]).Name,'');
+ for n := 0 to TRadioGroup(NowForm.Components[i]).Items.Count - 1 do
+ begin
+ TRadioGroup(NowForm.Components[i]).Items.Strings[n] := ini.ReadString(FLanguage,FormName+'.'+TRadioGroup(NowForm.Components[i]).Name+'_'+inttostr(n),'');
+ end;
+ end;
+ end;
+ finally
+ ini.Free;
+ end;
+end;
+
+function TCB_IMGPSScanX.GetSiteOMR(FileName,Site:String;bt: Integer): Integer;
+var
+ OMRRect : TRect;
+ Xdpi,Ydpi : Integer;
+ W,H : Integer;
+begin
+ Result := 0;
+//ShowMessage('GetSiteOMR');
+
+ IF (ImageScrollBox1.FileName <> FileName) and (FileName <> '') then
+ begin
+//ShowMessage('11111'+ImageScrollBox1.FileName+#10#13+FileName);
+ ImageScrollBox1.LoadFromFile(FileName,1);
+{
+ShowMessage('UpLPoint='+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+#10#13+
+'UpRPoint='+IntToStr(UpRPoint.X)+','+IntToStr(UpRPoint.Y)+#10#13+
+'DownLPoint='+IntToStr(DownLPoint.X)+','+IntToStr(DownLPoint.Y)+#10#13+
+'DownRPoint='+IntToStr(DownRPoint.X)+','+IntToStr(DownRPoint.Y));
+ FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'');
+ShowMessage('UpLPoint='+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+#10#13+
+'UpRPoint='+IntToStr(UpRPoint.X)+','+IntToStr(UpRPoint.Y)+#10#13+
+'DownLPoint='+IntToStr(DownLPoint.X)+','+IntToStr(DownLPoint.Y)+#10#13+
+'DownRPoint='+IntToStr(DownRPoint.X)+','+IntToStr(DownRPoint.Y));
+}
+ ClearLine(ISB_BW.Graphic,bt);
+ ISB_BW.Redraw(True);
+ Application.ProcessMessages;
+ end;
+ If ImageScrollBox1.FileName <> '' Then
+ begin
+
+//ShowMessage('22222'+ImageScrollBox1.FileName);
+ Xdpi := ImagescrollBox1.Graphic.XDotsPerInch;
+ Ydpi := ImagescrollBox1.Graphic.YDotsPerInch;
+ H := ImageScrollBox1.Graphic.Height;
+ W := ImageScrollBox1.Graphic.Width;
+//ShowMessage('Xdpi='+IntToStr(Xdpi)+#10#13+'Ydpi='+IntToStr(Ydpi)+#10#13+'H='+IntToStr(H)+#10#13+'W='+IntToStr(W)+#10#13);
+//ShowMessage('Site='+Site);
+ OMRRect := CM_Str2Rect(Site,Xdpi,UpLPoint);
+Display1.Lines.Add('UpLPoint=('+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+');'+Site+';'+IntToStr(OMRRect.Left)+','+IntToStr(OMRRect.top)+','+IntToStr(OMRRect.Right)+','+IntToStr(OMRRect.Bottom));
+ if OMRRect.Left < 0 then
+ OMRRect.Left := 0;
+ if OMRRect.Top < 0 then
+ OMRRect.Top := 0;
+ if OMRRect.Right > ImageScrollBox1.Graphic.Width then
+ OMRRect.Right := ImageScrollBox1.Graphic.Width;
+ if OMRRect.Bottom > ImageScrollBox1.Graphic.Height then
+ OMRRect.Bottom := ImageScrollBox1.Graphic.Height;
+
+ result := Get_OMR(ISB_BW.Graphic,OMRRect);
+//ShowMessage('result='+IntToStr(result));
+
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.DisplayMode(index,H_Count,W_Count:Integer;BasePanel:TPanel);
+Var
+ W,H,T,L:Integer;
+ i,n,Count: Integer;
+ Pl :TPanel;
+ bmp : TBitmap;
+begin
+ for i := 1 to 8 do
+ begin
+ TPanel(Findcomponent('imgp'+inttostr(i))).Visible := False;
+ end;
+ W := Round((BasePanel.Width - ((W_Count+1) * Seg)) / W_Count);
+ H := Round((BasePanel.Height -((H_Count+1) * Seg)) / H_Count);
+ Count := 1;
+ for i := 1 to H_Count do
+ begin
+ T := i * Seg + H * (i-1);
+ for n := 1 to W_Count do
+ begin
+ L := n * Seg + W * (n-1);
+ Pl := TPanel(Findcomponent('imgp'+inttostr(Count)));
+ Pl.Visible := True;
+ Pl.Left := L;
+ Pl.Top := T;
+ Pl.Width := W;
+ Pl.Height := H;
+ inc(Count);
+ end;
+ end;
+ Shape1.Width := W + (Seg * 2);
+ Shape1.Height := H + (Seg * 2);
+ Shape1.Visible := True;
+
+
+ bmp := Tbitmap.Create;
+ try
+ ImageList2.GetBitmap(index,bmp);
+ ViewModeBtn.Glyph.Assign(bmp);
+ finally
+ bmp.Free;
+ end;
+ ISB1Click(ISB1);
+end;
+
+Function TCB_IMGPSScanX.GetSampleInf : Boolean;
+var
+ str:String;
+begin
+ Result := False;
+ If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/serversampleforocx','work_no='+FWork_no,FReWrite,Memo1,False) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else IF memo1.Lines.Strings[0] = '0' Then
+ begin
+ str := memo1.Lines.Strings[1];
+ SampleFormIDList.CommaText:=str;
+
+ Result := True;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+
+end;
+
+function TCB_IMGPSScanX.CheckRequiredColumnValues(workno, caseno:String): Boolean;
+begin
+//
+ Result:=False;
+ if (workno='HLN') and (caseno[9]='3') then
+ Result:=True;
+ if (workno='HLN') and (caseno[9]='4') then
+ Result:=True;
+end;
+
+Procedure TCB_IMGPSScanX.CheckRule2OMRErrInfo; //檢核規則填入OMRErrINFo Record
+var i : Integer;
+ CheckNo : String;
+begin
+ for I := 1 to 11 do
+ begin
+ CheckNo := Add_Zoo(i,3);
+
+ if FindSQLData(CHECK_RULE_INF_List,'MESG_SHOW_TYPE,MESG_DISP_TYPE,CHECK_MESG,SCAN_MODE','CHECK_NO',CheckNo,0,FindResult) then
+ begin
+ if GetFindResult('MESG_SHOW_TYPE') = '1' then
+ OMRErrInfo[i].Display := True //顯示
+ Else if GetFindResult('MESG_SHOW_TYPE') = '2' then
+ OMRErrInfo[i].Display := False; //不顯示
+
+ if GetFindResult('MESG_DISP_TYPE') = '1' then
+ OMRErrInfo[i].Ignore := True //可忽略
+ Else if GetFindResult('MESG_DISP_TYPE') = '2' then
+ OMRErrInfo[i].Ignore := False; //不可忽略
+
+ OMRErrInfo[i].Info := GetFindResult('CHECK_MESG');
+ OMRErrInfo[i].Mode := GetFindResult('SCAN_MODE');
+ end;
+ end;
+end;
+
+
+
+Procedure TCB_IMGPSScanX.ReNameContext(Path,OldName,NewName:String);
+var
+ i : Integer;
+begin
+ for i := 0 to ContextList.Count - 1 do
+ begin
+ if OldName = ContextList.Strings[i] then
+ begin
+ ContextList.Strings[i] := NewName;
+ ContextList.SaveToFile(Path+'Context.dat');
+ Context_DocnoList.Strings[i] := FormCode2DocNo(FileName2FormCode(NewName));
+ Context_DocnoList.SaveToFile(Path+'Context_DocNo.dat');
+ Break;
+ end;
+ end;
+end;
+
+Function TCB_IMGPSScanX.Down_Img(Path,CaseID:String):Boolean;
+var
+ EnCodeDateTime : String;
+ SendData : String;
+ AttPath : String;
+begin
+ Result := True;
+ EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
+ ///service/slic/SLIC04/case?data=&verify=&case_no=&file=
+ SendData := 'data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&case_no='+CaseID+'&file=';
+//ShowMessage(SendData);
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ if Memo1.Lines.Strings[0] = '1' then
+ begin
+ HttpErrStr :=_Msg('錯誤原因:')+memo1.Lines.Strings[1]+'。';
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/IMGPS00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+//ShowMessage('替換zip');
+ AttPath := Path + 'AttFile\';
+ if FileExists(Path+CaseID+'.zip') then
+ begin
+ ExecuteUnZip(Path+CaseID+'.zip',Path,True);
+ if FileExists(Path+'img.zip') then
+ begin
+ ExecuteUnZip(Path+'img.zip',Path,False);
+ end;
+ if FileExists(Path+'att.zip') then
+ begin
+ Str2Dir(AttPath);
+ ExecuteUnZip(Path+'att.zip',AttPath,False);
+ end;
+ end
+ Else
+ begin
+ HttpErrStr := _Msg('找不到影像');
+ Result := True;
+ Exit;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.ClearErrini(CaseID:String;CaseNode:TTreeNode); //清掉檢核檔案
+var
+ i : Integer;
+begin
+ if FileExists(ImageSavePath+CaseID+'\Checkerr.ini') then
+ DeleteFile(ImageSavePath+CaseID+'\Checkerr.ini');
+ if FileExists(ImageSavePath+CaseID+'\CheckMemo.dat') then
+ DeleteFile(ImageSavePath+CaseID+'\CheckMemo.dat');
+ {if FileExists(ImageSavePath+CaseID+'\ReSize.dat') then //20110421拿掉 因為記錄會不見
+ DeleteFile(ImageSavePath+CaseID+'\ReSize.dat');}
+ if FileExists(ImageSavePath+CaseID+'\RemoveMemo.dat') then
+ DeleteFile(ImageSavePath+CaseID+'\RemoveMemo.dat');
+ if FileExists(ImageSavePath+CaseID+'\OMRCheckOk.dat') then
+ DeleteFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
+ CaseHelpBtn.Visible := False;
+ CaseNode.ImageIndex := 2;
+ CaseNode.SelectedIndex := 2;
+end;
+
+Procedure TCB_IMGPSScanX.SetContextList(Mode:Char;Index:Integer;CaseNo,DocDir,FileName:String); //'A:加入,I:插入,D:刪除,E:修改'
+var
+ i : Integer;
+ //DocNo:String;
+begin
+ //DocNo := FormCode2DocNo(FileName2FormCode(FileName));
+//ShowMessage('FileName='+FileName);
+ if DocDir = '' then
+ DocDir := AttName ; //附件
+ ContextList.Clear;
+ if FileExists(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat') then
+ ContextList.LoadFromFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');
+ SetRecordEditedDocDir('A',CaseNo,DocDir); //記錄文件有異動
+ case Mode of
+ 'A':begin
+ ContextList.Add(FileName);
+ end;
+ 'I':begin
+ ContextList.Insert(Index,FileName);
+ end;
+ 'E':begin
+ ContextList.Strings[Index] := FileName;
+ end;
+ 'D':begin
+ if Index <> -1 then
+ begin
+ ContextList.Delete(Index);
+ end
+ Else if (text <> '') then
+ begin
+ for i := 0 to ContextList.Count - 1 do
+ begin
+ if FileName = ContextList.Strings[i] then
+ begin
+ ContextList.Delete(i);
+ Break;
+ end;
+ end;
+ end;
+ if ContextList.Count = 0 then
+ DeleteFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');
+ end;
+ end;
+ if ContextList.Count > 0 then
+ begin
+ ContextList.SaveToFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.SetAttContextList(Mode:Char;Index:Integer;CaseNo,FileName:String); //'A:加入,I:插入,D:刪除,E:修改'
+var
+ i : Integer;
+begin
+ AttContextList.Clear;
+ if FileExists(ImageSavePath+CaseNo+'\AttContext.dat') then
+ AttContextList.LoadFromFile(ImageSavePath+CaseNo+'\AttContext.dat');
+ case Mode of
+ 'A':begin
+ AttContextList.Add(FileName);
+ end;
+ 'I':begin
+ AttContextList.Insert(Index,FileName);
+ end;
+ 'E':begin
+ AttContextList.Strings[Index] := FileName;
+ end;
+ 'D':begin
+ if Index <> -1 then
+ begin
+ AttContextList.Delete(Index);
+ end
+ Else if (text <> '') then
+ begin
+ for i := 0 to AttContextList.Count - 1 do
+ begin
+ if FileName = AttContextList.Strings[i] then
+ begin
+ AttContextList.Delete(i);
+ Break;
+ end;
+ end;
+ end;
+ if AttContextList.Count = 0 then
+ DeleteFile(ImageSavePath+CaseNo+'\AttContext.dat');
+ end;
+ end;
+ if AttContextList.Count > 0 then
+ begin
+ AttContextList.SaveToFile(ImageSavePath+CaseNo+'\AttContext.dat');
+ end;
+end;
+
+Function TCB_IMGPSScanX.ModeNeedCheck(OMRMode,ScanMode:String):Boolean; //掃瞄模式是否要做檢核
+begin
+ Result := False;
+ if Pos(ScanMode,OMRMode) > 0 then
+ Result := True;
+end;
+
+Function TCB_IMGPSScanX.FindNoSaveBarCode : Boolean; //找是否有不要儲存影像的條碼
+var
+ i,n : Integer;
+begin
+ Result := False;
+ for i := 1 to MpsBarcodeinf.Count do
+ begin
+ for n := 0 to NoSaveBarCodeList.Count - 1 do
+ begin
+ if MpsBarcodeinf.Text[i] = NoSaveBarCodeList.Strings[n] then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+ if Result then
+ Break;
+ end;
+end;
+
+Function TCB_IMGPSScanX.Index2Anchor(Anchor:String):String; //十字模式 0->NONE;1->ANCHOR;2->FRAME
+begin
+ if Anchor = '0' then
+ Result := 'NONE'
+ else if Anchor = '1' then
+ Result := 'ANCHOR'
+ else if Anchor = '2' then
+ Result := 'FRAME';
+end;
+
+Function TCB_IMGPSScanX.GetFindResult(Col:String):String;
+var
+ i,v,v1 : Integer;
+ S,RCol,RValue : String;
+begin
+ Result := '';
+ for I := 0 to FindResult.Count - 1 do
+ begin
+ S := FindResult.Strings[i];
+ v := Pos(',',S);
+ v1 := length(S);
+ RCol := copy(S,1,v-1);
+ RValue := Copy(S,v+1,v1-v);
+ if Col =RCol then
+ Result := RValue;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DrawDocItem2(CaseNode : TTreenode;Caseno:String):Boolean; //畫出文件名稱的Tree
+Var
+ i,n,m : Integer;
+ DocNode,FormNode : TTreeNode;
+ DocNoPage,FormPage : Integer;
+ DocNoCopies : Integer;
+ DocNo,iDocNo : String;
+ DocVer : String;
+ FileList : TStringlist;
+ FormID,iFormID : String;
+ FormName : String;
+ CaseDocNoList,CaseDocNo_CopiesList,StrList : TStringlist;
+ iiDocNo,iiFormID,iiDocVer : String;
+ ST1:TStringList;
+begin
+ Result := False;
+ FileList := TStringlist.Create;
+ CaseDocNoList := TStringlist.Create;
+ CaseDocNo_CopiesList := TStringlist.Create;
+ StrList := TStringlist.Create;
+ ST1:=TStringList.Create;
+LogFile1.LogToFile(logTimeString+'產文件樹開始');
+ try
+ CaseNode.ImageIndex := 1;
+ CaseNode.SelectedIndex := 1;
+ While CaseNode.Count > 0 do //全刪
+ begin
+ CaseNode.Item[0].Delete;
+ end;
+ CaseDocNoList.Clear;
+ if FileExists(ImageSavePath+Caseno+'\CaseDocNo.dat') then
+ CaseDocNoList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo.dat');
+ if FileExists(ImageSavePath+Caseno+'\CaseDocNo_Copies.dat') then
+ CaseDocNo_CopiesList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo_Copies.dat');
+ for i := 0 to CaseDocNoList.Count - 1 do
+ begin
+ FileList.Clear;
+ //Showmessage(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat');
+ if FileExists(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat') then
+ FileList.LoadFromFile(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat');
+ iDocNo := DocNoDir2DocNo(CaseDocNoList.Strings[i]);
+ ST1.Clear;
+
+LogFile1.LogToFile(logTimeString+'FileList.Text='+FileList.CommaText);
+ if (FWH_category='N') and (FIs_In_Wh='Y') then
+ begin
+ for n := 0 to FileList.Count - 1 do
+ begin
+ if ISExistImg(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\'+FileList.Strings[n]) then
+ begin
+ ST1.Add(FileList.Strings[n]);
+ end;
+ end;
+ for n := 0 to ST1.Count - 1 do
+ begin
+ if (FileList.IndexOf(ST1.Strings[n])<>-1) and (not DocNoIs_In_WH(iDocNo)) then
+ begin
+ FileList.Delete(FileList.IndexOf(ST1.Strings[n]));
+ end;
+ end;
+ end
+ Else
+ if not DocNoAppear(iDocNo) then Continue; //20180925 Hong覺得應該加這段
+
+
+
+LogFile1.LogToFile(logTimeString+'WH_category='+FWH_category+',Is_In_Wh='+FIs_In_Wh+',FileList.Text='+FileList.CommaText);
+ if FileList.Count=0 then Continue;
+
+ DocNoCopies := Strtoint(CaseDocNo_CopiesList.Strings[i]);
+ DocNoPage := FileList.Count;
+ iDocNo := DocNoDir2DocNo(CaseDocNoList.Strings[i]);
+//Showmessage(iDocNo);
+//Showmessage(DocNo2DocName(Caseno,iDocNo));
+//ShowMessage('FileList='+FileList.Text);
+ {if (((FIs_In_Wh = 'Y') and (not DocNoIs_In_WH(iDocNo))) or //入庫掃描不看非入庫文件
+ ((FIs_In_Wh = 'N') and (DocNoIs_In_WH(iDocNo)))) and
+ ((iDocNo <> 'Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then //非入庫掃描不看入庫文件
+ begin
+ Continue;
+ end;}
+
+ //if not DocNoAppear(iDocNo) then Continue;
+
+
+ //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('頁'),[CaseDocNoList.Strings[i],DocNo2DocName(Caseno,iDocNo),DocNoPage]));
+ //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[CaseDocNoList.Strings[i],DocNo2DocName(Caseno,iDocNo),DocNoCopies]));
+//ShowMessage('iDocNo='+iDocNo);
+ DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),CaseDocNoList.Strings[i],DocNoCopies]));
+
+ if GetUseCase('F',ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]) <> '' Then
+ begin
+ DocNode.ImageIndex := 8;
+ DocNode.SelectedIndex := 8;
+ end
+ Else if GetUseCase('T',ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]) <> '' Then
+ begin
+ DocNode.ImageIndex := 9;
+ DocNode.SelectedIndex := 9;
+ end
+ Else
+ begin
+ DocNode.ImageIndex := 2;
+ DocNode.SelectedIndex := 2;
+ end;
+ if ((Pos('ZZZZZ',DocNode.Text) = 0) and (Pos('YYYYY',DocNode.Text) = 0)) and (FileList.Count =0) then //制式文件
+ begin
+ for n := 1 to LASTEST_FORM_INF_List.Count - 1 do
+ begin
+ StrList := SplitString('!@!',LASTEST_FORM_INF_List.Strings[n]);
+ iiFormID := StrList.Strings[0];
+ iiDocNo := StrList.Strings[1];
+ if iiDocNo = iDocNo then
+ begin
+ FormID := iiFormID;
+ FormPage := GetFormIDPage(FileList,FormID);
+ FormName := FormCode2FormName(Caseno,FormID);
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
+ FormNode.ImageIndex := 4;
+ FormNode.SelectedIndex := 4;
+ DocNode.AlphaSort(True);
+ end;
+ end;
+ end
+ else if (Pos('ZZZZZ',DocNode.Text) > 0) or (Pos('YYYYY',DocNode.Text) > 0) then //自訂文件
+ begin
+ FormID := GetCustomFormID(ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]);
+ //showmessage(FileList.Text);
+ FormPage := GetFormIDPage(FileList,FormID);
+ FormName := FormCode2FormName(Caseno,FormID);
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
+ FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
+ FormNode.ImageIndex := 4;
+ FormNode.SelectedIndex := 4;
+ DocNode.AlphaSort(True);
+ end;
+ SortDocDir_FormID(Caseno,CaseDocNoList.Strings[i]); //檔名依FormID排序
+
+ for n := 0 to FileList.Count - 1 do
+ begin
+ FormID := FileName2FormCode(FileList.Strings[n]);
+ DocVer := FormCode2Version(FormID);
+ DocNo := FormCode2DocNo(FormID);
+ if CheckFormIDExists(DocNode,FormID) then Continue;
+ //Showmessage(FormID+#13+DocNo+#13+DocVer);
+ for m := 0 to FormID_List.Count - 1 do
+ begin
+ iiFormID := FormID_List.Strings[m];
+ iiDocNo := DocNo_List.Strings[m];
+ iiDocVer := FormCode2Version(iiFormID);
+ if (iiDocNo = DocNo) and (iiDocVer = DocVer) then
+ begin
+ //Showmessage(iiFormID+#13+iiDocNo+#13+iiDocVer);
+ FormID := iiFormID;
+ FormPage := GetFormIDPage(FileList,FormID);
+ FormName := FormCode2FormName(Caseno,FormID);
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
+ FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
+ FormNode.ImageIndex := 4;
+ FormNode.SelectedIndex := 4;
+ DocNode.AlphaSort(True);
+ end;
+ end;
+
+
+ //if not CheckFormIDExists(DocNode,FormID) then
+ //begin
+ // Application.ProcessMessages;
+ // FormPage := GetFormIDPage(FileList,FormID);
+ /// FormName := FormCode2FormName(Caseno,FormID);
+ /// FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ // FormNode.ImageIndex := 4;
+ // FormNode.SelectedIndex := 4;
+ //end;
+ end;
+ end;
+
+ if DirectoryExists(ImageSavePath+Caseno+'\'+AttName) then
+ begin
+
+ FileList.Clear;
+ if FileExists(ImageSavePath+Caseno+'\'+AttName+'\Context.dat') then
+ FileList.LoadFromFile(ImageSavePath+Caseno+'\'+AttName+'\Context.dat')
+ Else
+ begin
+ Rmdir(ImageSavePath+Caseno+'\'+AttName);
+ Exit;
+ end;
+ DocNoPage := FileList.Count;
+ iDocNo := DocNoDir2DocNo(AttName);
+ //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[AttName,DocNo2DocName(Caseno,iDocNo),1]));
+ DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),AttName,1]));
+ DocNode.ImageIndex := 2;
+ DocNode.SelectedIndex := 2;
+ for n := 0 to FileList.Count - 1 do
+ begin
+ FormID := FileName2FormCode(FileList.Strings[n]);
+ if not CheckFormIDExists(DocNode,FormID) then
+ begin
+ FormPage := GetFormIDPage(FileList,FormID);
+ FormName := FormCode2FormName(Caseno,FormID);
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
+ FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
+ FormNode.ImageIndex := 4;
+ FormNode.SelectedIndex := 4;
+ end;
+ end;
+ end;
+
+ if FModeName='件' then //20170904 先裝死 因為異動 同時存在兩種附件太難寫
+ begin
+ if DirectoryExists(ImageSavePath+Caseno+'\Attach') then
+ begin
+ FileList.Clear;
+ if FileExists(ImageSavePath+Caseno+'\Attach'+'\Context.dat') then
+ FileList.LoadFromFile(ImageSavePath+Caseno+'\Attach'+'\Context.dat')
+ Else
+ begin
+ Rmdir(ImageSavePath+Caseno+'\Attach');
+ Exit;
+ end;
+ DocNoPage := FileList.Count;
+ iDocNo := DocNoDir2DocNo(AttName);
+ //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[AttName,DocNo2DocName(Caseno,iDocNo),1]));
+ //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[DocNo2DocName(Caseno,iDocNo),'Attach',1]));
+ DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),'Attach',1]));
+
+ DocNode.ImageIndex := 2;
+ DocNode.SelectedIndex := 2;
+ for n := 0 to FileList.Count - 1 do
+ begin
+ FormID := FileName2FormCode(FileList.Strings[n]);
+ if not CheckFormIDExists(DocNode,FormID) then
+ begin
+ FormPage := GetFormIDPage(FileList,FormID);
+ FormName := FormCode2FormName(Caseno,FormID);
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
+ //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
+ FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
+
+ FormNode.ImageIndex := 4;
+ FormNode.SelectedIndex := 4;
+ end;
+ end;
+ end;
+ end;
+LogFile1.LogToFile(logTimeString+'產文件樹結束');
+ Finally
+ FileList.Free;
+ CaseDocNoList.Free;
+ CaseDocNo_CopiesList.Free;
+ StrList.Free;
+ ST1.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.initParameter;
+begin
+
+// if FCaseNoLength=0 then
+// begin
+//
+// end;
+
+ if FFileSizeLimit = 0 then
+ begin
+ FFileSizeLimit := 5*1024;
+ end;
+
+
+ if FImgDPI=0 then
+ begin
+ FImgDPI := 300;
+ ScanDpi := FImgDPI;
+ end
+ else
+ begin
+ //FImgDPI := StrToInt(Value);
+ ScanDpi := FImgDPI;
+ end;
+
+ if FScanColor = 0 then
+ begin
+ ScanColor := ifBlackWhite;
+ end;
+
+ if FScanColor = 1 then
+ begin
+ ScanColor := ifGray256 ;
+ ScanGrayCB.Checked:=True;
+ end;
+
+ if FScanColor = 2 then
+ begin
+ ScanColor := ifTrueColor ;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CheckAvailable:Boolean; //檢查是否可使用元件
+var
+ SendData : String;
+ Msg:String;
+ Nowcount,Totalcount,Lic_Idx : Integer;
+ MacID,IPStr,LegalDate :String;
+begin
+ Result := False;
+ /////下載MPSLIC_SCAN.lic //////
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&work_no=PLN&file=MPSLIC_SCAN.lic';
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ Showmessage(_Msg('檢查註冊檔案時,網路發生錯誤!!')+_Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason);
+ Exit;
+ end;
+ /////下載MPSLIC_SCAN.lic ///
+
+ if CheckLicensebyIP_new(LngPath+'MPSLIC_SCAN.lic',MacID,IPStr,LegalDate,Msg,Nowcount,Totalcount,Lic_Idx) then //檢查是否己註冊過
+ begin
+ if (LegalDate <> '') and (ServerDate>LegalDate) and (Lic_Idx>(Totalcount)) then
+ begin
+ Showmessage(_Msg('已經超過可使用期限及超出授權數請連絡廠商'));
+ Result := False;
+ //Exit;
+ end
+ else
+ Result := True;
+ end
+ Else
+ begin
+ if Msg <> '' then
+ begin
+ Showmessage(Format(_Msg('註冊檔有問題,請連絡廠商 錯誤原因:%s'),[Msg]));
+ Result := false;
+ Exit;
+ end
+ Else
+ begin
+ if (LegalDate <> '') and (ServerDate>LegalDate) and (NowCount =0 ) then
+ begin
+ Lic_Idx := 0;
+ Showmessage(_Msg('已經超過可使用期限請連絡廠商'));
+ Result := False;
+ //Exit;
+ end
+ //else if (LegalDate = '') and (Nowcount >= Totalcount+10) then //超過註冊數量
+ else if ((LegalDate = '') or ((LegalDate <> '') and (ServerDate>LegalDate)) ) and (Nowcount >= Totalcount) then //超過註冊數量 20150717 yuu說拿掉送的10個
+ begin
+ Lic_Idx := 0;
+ Showmessage(_Msg('已經超過授權數請連絡廠商'));
+ Result := False;
+ end
+ Else //未超過註冊數量要寫入註冊檔
+ begin
+ {if Messagedlg(_Msg('您尚未註冊授權是否要進行註冊??'),MtConfirmation,[mbyes,mbcancel],0) = mrcancel then
+ begin
+ Result := False;
+ Exit;
+ end;}
+ ShowText := _Msg('授權中,請稍候');
+ AddLicense(LngPath+'MPSLIC_SCAN.lic',MacID,IPStr,Msg);
+ Nowcount := Nowcount + 1;
+ DataLoading(True,True);
+
+ /////上傳MPSLICSCAN.lic ////
+ SendData:='data='+HTTPEncode(UTF8Encode(FData))+'@verify='+FVerify+'@work_no=PLN@file_name=MPSLIC_SCAN.lic';
+ if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False) then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
+ DataLoading(False,False);
+ Exit;
+ end;
+ if memo1.Lines.Strings[0] = '1' then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
+ DataLoading(False,False);
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ Showmessage(_Msg('檢查註冊時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
+ DataLoading(False,False);
+ Exit;
+ end;
+ /////上傳MPSLICSCAN.lic /////
+ //Sleep(30000); //第一次註冊睡30秒 先不睡
+ Result := True;
+ end;
+ end;
+ end;
+ if FileExists(LngPath+'MPSLIC_SCAN.lic') then
+ DeleteFile(LngPath+'MPSLIC_SCAN.lic');
+ if LegalDate = '' then
+ StatusBar1.Panels[4].Text := Format(_Msg('註冊號:%s 剩餘註冊數:%s'),[MacID,inttostr(Totalcount-Nowcount)]);
+ if LegalDate <> '' then
+ StatusBar1.Panels[4].Text := '*'+Format(_Msg('註冊號:%s 剩餘註冊數:%s'),[MacID+'('+inttostr(Lic_Idx)+')',inttostr(Totalcount-Nowcount)]);
+end;
+
+Function TCB_IMGPSScanX.GetCustomDocName(Path,DocNo:String):String; //取出自定文件名稱
+var
+ ini : Tinifile;
+begin
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ Result := ini.ReadString(DocNo,'Name','');
+ finally
+ ini.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.FindCustomDocName(Path,DocName:String):Boolean; //尋找自定文件名稱是否存在
+var
+ ini : Tinifile;
+ Ct,i:Integer;
+ DocNo,FormID : String;
+begin
+ Result := False;
+ ini := Tinifile.Create(Path+'CustomDocNo.ini');
+ try
+ Ct := ini.ReadInteger('CustomCount','Count',0);
+ for I := 1 to Ct do
+ begin
+ DocNo := 'ZZZZZ'+Add_Zoo(i,3);
+ if DocName = ini.ReadString(DocNo,'Name','') then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+ finally
+ ini.Free;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.PrintImg(FileName, LoginID, Datetime,
+ Path: WideString);
+var
+ PrintMode : TEnvisionPrintMode;
+ GraphicPrinter : TDibGraphicPrinter;
+ PrtDialog : TPrintDialog;
+ S : TStringlist;
+ i,Pages,Page : Integer;
+ Prt_String : String;
+ Prt_H : Integer;
+ procedure PrintWithManualPrintJob(LoginID,DateTime:String;Pages,Page:Integer);
+ begin
+ If Page = 1 Then
+ begin
+ { if UsePrintJob is False, Printer.BeginDoc and Printer.EndDoc must be
+ called by the user. This allows printing multiple images in the
+ same job (or page). }
+ GraphicPrinter.UsePrintJob := False;
+
+ { if UsePrintJob is False, the print job name that appears in the
+ print manager must be specified in using the Title property of the
+ Printer object. Otherwise, if UsePrintJob is True, the Title
+ property of the TDibGraphicPrinter object is used to specify the
+ job name. }
+ Printer.Title := _Msg('影像列印');
+ end;
+
+ IF (Page mod 2) = 1 Then
+ Printer.BeginDoc
+ Else
+ Printer.NewPage;
+
+ ImageScrollBox1.DisplayedGraphic.Canvas.Font.Size := 24;
+
+ //ImageScrollBox1.DisplayedGraphic.Canvas.TextOut(20,20, _Msg('列印人員:')+LoginID+' '+_Msg('列印分行:')+FUserUnit+' '+_Msg('列印日期:')+DateTime);
+
+ GraphicPrinter.Print(ImageScrollBox1.DisplayedGraphic);
+
+
+ { this shows how to print text on a page.
+ Printer.Canvas.TextOut(10,10, 'Envision Image Library');
+ }
+ If ((Page mod 2) = 0) or (Page = pages) Then
+ Printer.EndDoc;
+ end;
+
+ procedure PrintWithAutoPrintJob;
+ begin
+ GraphicPrinter.UsePrintJob := True;
+ GraphicPrinter.Title := _Msg('影像列印');
+ GraphicPrinter.Print(ImageScrollBox1.Graphic);
+ end;
+
+begin
+ S := TStringlist.Create;
+ GraphicPrinter := TDibGraphicPrinter.Create;
+ PrtDialog := TPrintDialog.Create(self);
+ //PrtDialog.Copies:=99;
+ try
+ IF PrtDialog.Execute Then
+ begin
+ S.Text := FileName;
+ Pages := S.Count;
+
+ for i := 0 to S.Count -1 do
+ begin
+ ImageScrollBox1.LoadFromFile(Path+S.Strings[i],1);
+ watermark2(Image1.Picture.Bitmap,70,'',ImageScrollBox1.DisplayedGraphic);
+ PrintWithManualPrintJob(LoginID,DateTime,Pages,i+1);
+ end;
+ end;
+
+ Finally
+ PrtDialog.Free;
+ GraphicPrinter.Free;
+ S.Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.GotoAttach(OldLevel:Integer);
+var
+ i : Integer;
+begin
+ for i := 0 to MyTreeNode1.Count - 1 do
+ begin
+ if Pos('Attach',MyTreeNode1.Item[i].Text) > 0 then
+ begin
+ if OldLevel = 2 then
+ begin
+ TreeView1.Selected := MyTreeNode1.Item[i];
+ end
+ else if OldLevel = 3 then
+ begin
+ TreeView1.Selected := MyTreeNode1.Item[i].Item[0];
+ end;
+ Break;
+ end;
+ end;
+ //TreeView1click(nil);
+end;
+
+Function TCB_IMGPSScanX.GetCustomNameCount(CustomName:String):Integer; //取外傳的名稱數量
+var
+ i,ct : Integer;
+ C_DocNameList : TStringlist;
+begin
+ C_DocNameList := TStringlist.Create;
+ try
+ C_DocNameList.StrictDelimiter := True;
+ C_DocNameList.Delimiter := #9;
+ C_DocNameList.DelimitedText := FC_DocNameList;
+ ct := 0;
+ for i := 0 to C_DocNameList.Count - 1 do
+ begin
+ if C_DocNameList.Strings[i] = CustomName then
+ begin
+ inc(ct);
+ end;
+ end;
+ Result := ct;
+ finally
+ C_DocNameList.Free;
+ end;
+end;
+
+function TCB_IMGPSScanX.ISExistImg(const filename: string): boolean;
+begin
+ if ExistImgList.IndexOf(LoadFileGetMD5(filename))<>-1 then
+ begin
+ Result:=True;
+ end
+ else
+ begin
+ Result:=False;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.PriorPage(Page:Integer); //上一頁
+var
+ iISB : TImageScrollBox;
+begin
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(Page-1)));
+ if iISB <> nil then
+ begin
+ ISBClick(iISB);
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.NextPage(Page:Integer); //下一頁
+var
+ iISB : TImageScrollBox;
+begin
+ iISB := TImageScrollBox(FindComponent(ISBName+inttostr(Page+1)));
+ if iISB <> nil then
+ begin
+ ISBClick(iISB);
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.OMRErr2ini(CaseID,Reason,FileName,Site,RelaFileName,RelaSite,Anchor,Anchor1:String;Del,Ingnore,Display:Boolean); //OMR檢核失敗寫入ini
+var
+ ini : Tinifile;
+ Errcount : Integer;
+ S : TStringlist;
+begin
+ if Display then
+ begin
+ ini := Tinifile.Create(ImageSavePath + CaseID+'\upload\Checkerr.ini');
+ try
+ Errcount := ini.ReadInteger('OMRCount','Count',0); //透過Errcount來對應
+ inc(ErrCount);
+ ini.WriteString(inttostr(ErrCount),'Reason',Reason);
+ ini.WriteBool(inttostr(ErrCount),'Ingnore',Ingnore);
+ ini.writeString(inttostr(ErrCount),'FileName',FileName);
+ ini.WriteString(inttostr(ErrCount),'Site',Site);
+ ini.WriteString(inttostr(ErrCount),'RelaFileName',RelaFileName);
+ ini.WriteString(inttostr(ErrCount),'RelaSite',RelaSite);
+ ini.WriteString(inttostr(ErrCount),'Anchor',Anchor);
+ ini.WriteString(inttostr(ErrCount),'RelaAnchor',Anchor1);
+ ini.WriteBool(inttostr(ErrCount),'Del',Del);
+ ini.WriteInteger('OMRCount','Count',ErrCount);
+ finally
+ ini.Free;
+ end;
+ end
+ Else
+ begin
+ S := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath + CaseID+'\CheckMemo.dat') then
+ S.LoadFromFile(ImageSavePath + CaseID+'\CheckMemo.dat');
+ S.Add(Reason);
+ S.SaveToFile(ImageSavePath + CaseID+'\CheckMemo.dat');
+ finally
+ S.Free;
+ end;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.OMRErrini2List(CaseID:String;ErrlistForm:TErrlistForm); //OMR檢核失敗從ini寫入ListView
+var
+ ini : Tinifile;
+ Errcount : Integer;
+ Del : Boolean;
+ i : Integer;
+begin
+ ini := Tinifile.Create(ImageSavePath + CaseID+'\upload\Checkerr.ini');
+ try
+ Errcount := ini.ReadInteger('OMRCount','Count',0);
+
+ for i := 1 to ErrCount do
+ begin
+ Del := ini.ReadBool(inttostr(i),'Del',False); //是否被移除了
+ if Not Del then
+ begin
+ With ErrlistForm.ErrListLV.Items.Add do
+ begin
+ Caption := ini.ReadString(inttostr(i),'Reason','');
+ SubItems.Add(inttostr(i));
+ end;
+ end;
+ end;
+ if Errlistform.ErrListLV.Items.Count > 0 then
+ Errlistform.ImmediateBt.Enabled := False;
+ finally
+ ini.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.DownLanguage:Boolean; //下載多國語言檔
+begin
+ Result := True; // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
+ //dnFile(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite.Text,Memo1,False,DownImgStatus)
+ If not dnFile_Get(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite,Memo1,False,DownImgStatus) Then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ IF memo1.Lines.Strings[0] = '1' Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+
+end;
+
+Procedure TCB_IMGPSScanX.FreeShapeobj(SelectISB : TImageScrollBox);
+var
+ i : Integer;
+begin
+ IF SelectISB = nil then //全Free;
+ begin
+ For i:= ComponentCount -1 downto 0 do
+ begin
+ IF Components[i] is TShape Then
+ begin
+ IF Pos('SP',Components[i].Name) > 0 Then
+ Components[i].Free;
+ end;
+ end;
+ end
+ Else //只Free指定的
+ begin
+ TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))).Free;
+ end;
+end;
+
+Procedure TCB_IMGPSScanX.CreateIn_WH(CaseID:String); //產生In_WH.dat
+var
+ i,n : Integer;
+ DocDirList,In_WH_List : TStringlist;
+ iDocNo : String;
+begin
+ DocDirList := TStringlist.Create;
+ In_WH_List := TStringlist.Create;
+ try
+ if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
+ DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
+ for i := 0 to DocDirList.Count - 1 do
+ begin
+ iDocNo := DocNoDir2DocNo(DocDirList.Strings[i]);
+ for n := 0 to IN_WH_DocNoList.Count - 1 do
+ begin
+ if (iDocNo = IN_WH_DocNoList.Strings[n]) or (Copy(iDocNo,1,5)='ZZZZZ') then
+ begin
+ In_WH_List.Add(DocDirList.Strings[i]);
+ Break;
+ end;
+ end;
+ end;
+ In_WH_List.SaveToFile(ImageSavePath+CaseID+'\In_Wh.dat');
+
+ finally
+ DocDirList.Free;
+ In_WH_List.Free;
+ end;
+end;
+
+Function TCB_IMGPSScanX.CreateAttach_Info(CaseID:String):String; //產生是否有Attach Y:有 N:沒有
+begin
+ Result := 'N';
+ if GetDocDir_Page(CaseID,AttName) > 0 Then
+ Result := 'Y';
+end;
+
+Function TCB_IMGPSScanX.GetOMRCheckSet : Boolean; //下載OMR檢核XML檔
+var
+ SendData : String;
+ LastDateTime : String;
+ S : TStringlist;
+begin
+ Result := True;
+ S := TStringlist.Create;
+ Try
+ if FileExists(CheckXmlPath+'OMRSet.zip') then
+ DeleteFile(CheckXmlPath+'OMRSet.zip');
+
+ LastDateTime := '00000000000000';
+ if FileExists(CheckXmlPath+'LastDateTime.dat') then
+ begin
+ S.LoadFromFile(CheckXmlPath+'LastDateTime.dat');
+ LastDateTime := S.Strings[0];
+ end;
+
+ SendData := 'settype=3&lastupdate='+LastDateTime;
+ if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then
+ begin
+ HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
+ Result := False;
+ Exit;
+ end;
+ if FileExists(CheckXmlPath+'OMRSet.zip') then //有更新
+ begin
+ ExecuteUnZip(CheckXmlPath+'OMRSet.zip',CheckXmlPath,True);
+ S.Clear;
+ S.Add(ServerDate+GetBalance2Time(Balance));
+ S.SaveToFile(CheckXmlPath+'LastDateTime.dat');
+ end
+ Else
+ begin
+ if (Memo1.Lines.Strings[0] = 'nodata') Then //沒更新
+ begin
+ Result := True;
+ end
+ Else if (Memo1.Lines.Strings[0] = '1') Then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
+ Result := False;
+ Exit;
+ end
+ Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
+ begin
+ HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
+ Result := False;
+ Exit;
+ end;
+ end;
+
+ Finally
+ S.Free;
+ End;
+
+end;
+
+procedure TCB_IMGPSScanX.Timer1Timer(Sender: TObject);
+var
+ StampDate,StampTime : String;
+ i: Integer;
+begin
+ Timer1.Enabled := False;
+ //FIs_In_Wh:='Y'; /// test 記得關掉
+ //FWH_category :='N'; // test 記得關掉
+// FImgDelete := 'Y'; //test 記得關掉
+ //Showmessage('a');
+ //self.FIs_OldCase := 'Y';
+ PageLVclear := True;
+ InitialOk := False;
+
+ FMaxUploadSize:='10';
+ FJpgCompression:=50;
+ FFtpRootPath := ''; //影像平台沒有給FtpRoot目錄,會直接用FFtpExtraPath切換至指定目錄
+ //FMode := 'DSCAN' ;
+ //FIs_In_Wh := 'Y';
+ if FIs_In_Wh = 'Y' then
+ AttName := 'Attach' //入庫附件
+ else
+ AttName := 'S_Attach'; //Smartlending 附件
+//ShowMessage('1111111');
+ if FMode = 'SAMPLESCAN' then
+ begin
+ NewScanBtn.Visible := False;
+ PJLinkedMenuSpeedButton2.Visible := False;
+ AddScanBtn.Visible := False;
+ CheckCaseBtn.Visible := False;
+ Panel18.Visible := False;
+ TransBtn.Visible := False;
+ FC6.Visible := False;
+ SampleScanBtn.Visible := True;
+ Panel1.Visible := True;
+ Panel6.Visible := True;
+ ScanDuplexCB.Visible := False; //雙面掃描
+ end
+ Else if (FMode = 'NSCAN') then
+ begin
+ Panel18.Visible := True;
+ Panel1.Visible := True;
+ Panel6.Visible := True;
+ Panel21.Visible := True;
+ Panel23.Visible := True;
+
+ AttFileGB.Visible := True;
+ Splitter2.Visible := True;
+ ScanDuplexCB.Visible := True; //雙面掃描
+ end
+ Else if FMode = 'FSCAN' then
+ begin
+ Panel1.Visible := True;
+ //Panel6.Visible := True;
+ end
+ Else
+ begin
+ Panel18.Visible := True;
+ Panel1.Visible := True;
+ Panel6.Visible := True;
+ Panel21.Visible := True;
+ Panel23.Visible := True;
+ AttFileGB.Visible := True;
+ Splitter2.Visible := True;
+ end;
+ DisplayMode(1,1,1,Panel9);
+ Application.ProcessMessages;
+ StatusBar1.Panels[0].Text := 'Ver'+GetCurrentVersionNo;
+ StatusBar1.Panels[1].Text := 'Login User:'+FUserName;
+ {$IFDEF Test}
+ StatusBar1.Panels[0].Text := StatusBar1.Panels[0].Text+'(test)';
+ {$ENDIF}
+ StatusBar1.Panels[0].Text := StatusBar1.Panels[0].Text;
+
+ if FPrintyn = 'Y' then
+ PrtLB.Visible := True;
+
+ initParameter; //20170222 針對新加的parameter 作初始化參數
+ InitScrollRec;
+ If FUrl = '' then
+ begin
+ Showmessage(_Msg('URL cannot be empty,please contact system administrator'));
+ Exit;
+ end;
+ if FUrl[length(FUrl)]<>'/' then
+ FUrl := FUrl + '/';
+ //20221028 把語言檔改放至 Local目錄裡,才不會有些文字來不及使用
+ LngPath := GetLocalAppDir(Handle)+'MPS\CB_IMGPS\';
+ Str2Dir(LngPath);
+ ////下載語言檔///// 20170218 先拿調以便測試
+ If not DownLanguage Then
+ begin
+ Showmessage('Language File error!!'+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+
+ InitialLanguage(Self); //載入多國語言
+
+
+ if FWork_no='' then
+ begin
+ Showmessage(_Msg('業務別不能為空白,請洽詢程式人員'));
+ Exit;
+ end;
+
+ if CaseIDLength = 0 then
+ begin
+ Showmessage(_Msg('案件編號長度限制不能為空白,請洽詢程式人員'));
+ //Exit; //測試時不退出
+ end;
+
+ //********清單區********
+
+ Doc_Inf_List := TStringList.Create; //Doc_Inf 清單 Docno + 版本為key
+ DM_FORM_INF_List := TStringList.Create; //DM_FORM_INF 清單 Docno + 版本為key
+ FORM_INF_List := TStringList.Create; //FORM_INF的清單
+ CHECK_RULE_INF_List := TStringList.Create; //CHECK_RULE_INF 清單
+ MEMO_INF_List := TStringList.Create; //MEMO_INF 清單
+ WORK_INF_List := TStringList.Create; //WORK_INF 清單
+ LASTEST_FORM_INF_List := TStringList.Create; // LASTEST_FORM_INF 清單
+ FindResult := TStringlist.Create; //找SQLData的結果
+
+ OMRFileList := TStringList.Create; //要OMR檢核的文件(只檢查每種Form的第一頁)
+ FormCode_PageSize := TStringList.Create; //文件的預設大小 FormCode_Height_Width
+ DocNo_NeedDoc := TStringList.Create; //有Docno時要相依的文件 DocNo_相依文件_相依文件
+ DocNo_NoDoc := TStringList.Create; //有Docno時互斥的文件 DocNo_互斥文件_互斥文件
+ DocNo_VerinCase := TStringList.Create; //案件裡的DocNo+版本的清單
+ CaseDocNoList := TStringlist.Create; //案件裡的DocNo清單
+ CaseDocNo_CopiesList := TStringlist.Create; //案件裡的DocNo份數清單
+ CaseList := TStringList.Create; //記錄掃瞄案件的順序
+ Context_DocnoList := TStringlist.Create; //案件裡的檔案Docno清單
+ ContextList := TStringlist.Create; //案件裡的檔案清單
+ AttContextList := TStringlist.Create; //案件裡的附加檔案清單
+ NoSaveBarCodeList := TStringlist.Create; //不儲存的條碼清單
+ FormID_List := TStringlist.Create; //FormID清單
+ DocNo_List := TStringlist.Create; //DocNo清單
+ NowShowFileList := TStringlist.Create; //目前顯示的影像清單
+ NowSelectFileList := TStringlist.Create; //目前被點選的影像清單
+ Cust_DocNoList := TStringlist.Create; //自行定義的文件名稱
+ IN_WH_DocNoList := TStringlist.Create; //入庫的文件清單
+ GuideFormIDList := TStringlist.Create; //要當導引頁表單清單
+ DivPageFormIDList := TStringList.Create; //要當分案頁表單清單
+ LastInitFormidList :=TStringList.Create;
+ LastAddFormidList := TStringList.Create;
+ SampleFormIDList := TStringList.Create;//20170627 加入
+ ExistImgList := TStringList.Create; //20170724 新增
+ reSizeExistImgList :=TStringList.Create; //20171012 新增
+ //********清單區********
+
+ ShowText := _Msg('資料載入中,請稍候');
+ DataLoading(True,True);
+
+ IF not GetServerDate Then
+ begin
+ Showmessage(_Msg('取主機時間時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+
+ if FMode='SAMPLESCAN' then
+ begin
+ IF not GetSampleInf Then //取已存在sample
+ begin
+ Showmessage(_Msg('取存在範本資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+ end;
+
+
+
+//ShowMessage('GetServerDate '+ServerDate+' , '+ServerTime);
+ ////下載系統資訊////
+ IF not GetSetInf1 Then //取DOC_INF 文件資訊
+ begin
+ Showmessage(_Msg('取文件資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf1');
+ //showmessage(self.Doc_Inf_List.Text);
+ IF not GetSetInf2 Then //取DM_FORM_INF 相依互斥資訊
+ begin
+ Showmessage(_Msg('取相依互斥資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf2');
+ //Showmessage(self.Doc_Inf_List.Text);
+ IF not GetSetInf3 Then //取FORM_INF 表單資訊
+ begin
+ Showmessage(_Msg('取表單資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf3');
+ IF not GetSetInf4 Then //取CHECK_RULE_INF 檢核規則資訊
+ begin
+ Showmessage(_Msg('取檢核規則資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+ //showmessage(self.CHECK_RULE_INF_List.Text);
+//ShowMessage('GetSetInf4');
+ IF not GetSetInf5 Then //取MEMO_INF 常用片語資訊
+ begin
+ Showmessage(_Msg('取常用片語資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf5');
+ //showmessage(self.MEMO_INF_List.Text);
+ IF not GetSetInf6 Then //取WORK_INF 系統參數資訊
+ begin
+ Showmessage(_Msg('取系統參數資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf6');
+ //showmessage(FORM_INF_List.Text);
+ IF not GetSetInf7 Then //取LASTES_FORM_INF 系統參數資訊
+ begin
+ Showmessage(_Msg('取最新版FORMID參數資訊時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+//ShowMessage('GetSetInf7');
+ //Showmessage(LASTEST_FORM_INF_List.Text);
+ SetFormID_DocNo; //將FormID及Docno抽出塞入List裡 20130403增加
+ SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
+ GetDefScanIni; //取得掃描預設值及相關設定
+
+ ////下載系統資訊/////
+ if ImagePath = '' then
+ begin
+ Showmessage(_Msg('本機暫存路徑不得為空白'));
+ DataLoading(False,False);
+ Panel1.Enabled := False;
+ Panel2.Enabled := False;
+ Exit;
+ end;
+ initkscan;
+ if ImagePath[Length(ImagePath)] <> '\' then
+ ImagePath := ImagePath + '\';
+//ShowMessage('ImagePath='+ImagePath);
+ //CheckXmlPath := ImagePath+'OMRSITE\'+FWork_No;
+ CheckXmlPath := ImagePath+'OMRSITE\'; // 20200612 發現影像平台是取回所有業務的設定,所以不能有業務別目錄
+//ShowMessage('CheckXmlPath='+CheckXmlPath);
+ //SitePath := ImagePath+'Site\'+FWork_No+'\';
+ SitePath := ImagePath+'Site\'; // 20200612 發現影像平台是取回所有業務的設定,所以不能有業務別目錄
+ //LngPath := ImagePath; //改放至上面取Local目錄
+ SamplePath := ImagePath+'Sample\'+FWork_No+'\';
+ ImagePath := ImagePath + 'Scantemp\';
+//ShowMessage('AA ImagePath='+ImagePath);
+ ScaniniPath :=ImagePath+FWork_No+'\'+FUserUnit +'\';
+//ShowMessage('ScaniniPath='+ScaniniPath);
+ ImagePath := ImagePath + FWork_No+'\'+FUserUnit+'\'+FMode+'\';
+ ImagePath := StringReplace(ImagePath, '\\', '\',[rfReplaceAll, rfIgnoreCase]);
+//ShowMessage('BB ImagePath='+ImagePath);
+ ImageSavePath := ImagePath;
+ str2dir(CheckXmlPath);
+ str2dir(SitePath);
+ str2dir(ImagePath);
+ str2dir(SamplePath);
+ Del_Sub_NothingPath(ImagePath); //清掉案件目錄是空的
+
+
+ LogFile1.LogFile:=LngPath+'IMGPSCheck.log';
+
+ ReduceLogFile;
+
+ LogFile1.LogToFile(logTimeString+'OCX取表data結束');
+
+ ShowText := _Msg('資料載入中,請稍候');
+ DataLoading(True,True);
+
+// if not CheckAvailable Then //檢查授權 20170218 說不用了
+// begin
+// DataLoading(False,False);
+// Panel1.Enabled := False;
+// Panel2.Enabled := False;
+// Exit;
+// end;
+
+//Button3Click(Self);
+//ShowMessage('CheckAvailable');
+ ShowText := _Msg('資料載入中,請稍候');
+ DataLoading(True,True);
+
+
+ StatusBar1.Panels[1].Text := _Msg('登入人員:')+FUserName;
+ //FCaseID:='20150302180133';//測試用
+ ////下載語言檔/////
+//ShowMessage('OOOO');
+
+ if (FMode = 'RSCAN') or (FMode = 'DSCAN') or (FMode = 'ESCAN') or (FMode = 'FSCAN') then //重掃件及異動件要只能掃指定編號的件
+ begin
+ _Deltree(ImagePath);
+ str2dir(ImagePath);
+ ImageSavePath := ImagePath;
+ str2dir(ImageSavePath);
+ MkDir(ImageSavePath+FCaseID);
+ CreateEmptyCase(ImageSavePath,FCaseID);
+ MkDir(ImageSavePath+FCaseID+'\Download');
+ IF (FMode = 'ESCAN') or (FMode = 'DSCAN') then //異動件先下載影像
+ begin
+ ShowText := _Msg('案件下載中,請稍候');
+ DataLoading(True,True);
+ If not DownLoadImage(ImageSavePath+FCaseID+'\Download\',FCaseID) Then
+ begin
+ Showmessage(FCaseID+_msg('載入異動影像時,網路發生錯誤')+DownFileErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+
+ {If not Down_Img(ImageSavePath+FCaseID+'\Download\',FCaseID) then
+ begin
+ Showmessage(FCaseID+_msg('載入異動影像時,網路發生錯誤')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;}
+//Showmessage(ImageSavePath+FCaseID+'\Download\'+#10#13+ImageSavePath+FCaseID+'\');
+ Download2Case(ImageSavePath+FCaseID+'\Download\',ImageSavePath+FCaseID+'\');
+//Showmessage('aaa');
+ //Download2Case('C:\Users\Hong\Downloads\沒有括號\',ImageSavePath+FCaseID+'\');
+ if (FIs_OldCase = 'Y') then
+ begin
+ if (FWork_no='HLN') then
+ ErrFormtoCurrentForm(FCaseID,'10000001011112A','11000001011112A'); //換掉錯的FormID
+ //if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then //這個會在Download2Case時一律產生所以不能有這行 20141013
+ OldCasetoNewCase(FCaseID);
+ //ErrFormtoCurrentForm(FCaseID,'11B00005011312A','11000001011112A'); //換掉錯的FormID
+ //LoadImgFile;
+ end;
+// if (FIs_OldCase = 'Y') and (FWork_no='HLN') then //77版的
+// begin
+// ErrFormtoCurrentForm(FCaseID,'10000001011112A','11000001011112A'); //換掉錯的FormID
+// if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then
+// OldCasetoNewCase(FCaseID);
+// //ErrFormtoCurrentForm(FCaseID,'11B00005011312A','11000001011112A'); //換掉錯的FormID
+// //LoadImgFile;
+// end;
+ Create_Cust_DocDir(FCaseID); //產生外面傳入的文件
+ if FMode='ESCAN' then
+ LastInitFormidListCreate(ImageSavePath+FCaseID+'\Download\');
+ end;
+ end;
+
+//ShowMessage('GetOMRCheckSet前');
+ ////下載檢核XML//////
+ IF not GetOMRCheckSet Then
+ begin
+ Showmessage(_Msg('下載檢核定位檔案時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+ ////下載檢核XML/////
+//ShowMessage('GetOMRCheckSet後來');
+ ////下載登打設定/////
+ IF not GetKeyinSet Then
+ begin
+ Showmessage(_Msg('下載登打定位檔案時,網路發生錯誤!!')+HttpErrStr);
+ DataLoading(False,False);
+ Exit;
+ end;
+ ////下載登打設定/////
+//ShowMessage('GetKeyinSet');
+ if ScanDenialHint <> '' then //有設定提示字串就秀在右上角
+ begin
+ DenialTimeLb.Visible := True;
+ DenialTimeLb.Caption := Format(ScanDenialHint,[ScanDenialTime]);
+ end;
+//ShowMessage(IntToStr(ScanDpi));
+ R_W_Scanini('R'); //掃瞄設定的ini
+//ShowMessage(IntToStr(ScanDpi));
+//ShowMessage('停掉DataLoading');
+//DataLoading(False,False);
+ ScanDuplexCB.Checked := ScanDuplex;
+ if FMode <> 'SAMPLESCAN' then
+ LoadImgFile;
+ if (FMode = 'RSCAN') or (FMode = 'ESCAN') or (FMode = 'FSCAN') then
+ begin
+ if TreeView1.Items.Count > 0 then
+ begin
+ TreeView1.Selected := NewTreeNode.Item[0];
+ TreeView1click(self);
+ end;
+ end;
+ InitialOk := True;
+
+ {AttFileGB.Visible := True; //附加電子檔窗 //20120207楊玉說不在這加電子檔先拿掉
+ Splitter2.Visible := True;
+ AttFileGB.Visible := False; //附加電子檔窗
+ Splitter2.Visible := False; }
+//ShowMessage('ImageSavePath='+ImageSavePath);
+ DataLoading(False,False);
+
+ LogFile1.LogToFile(logTimeString+'OCX初始化結束');
+ LogFile1.LogToFile(logTimeString+'FUrl='+FUrl+
+ ',FCaseID='+FCaseID+
+ ',FMode='+FMode+
+ ',FModeName='+FModeName+
+ ',FWork_no='+FWork_no+
+ ',FUserID='+FUserID+
+ ',FUserName='+FUserName+
+ ',FUserUnit='+FUserUnit+
+ ',FData='+FData+
+ ',FVerify='+FVerify+
+ ',FReWrite='+FReWrite+
+ ',FLanguage='+FLanguage+
+ ',FLoanDoc_Value='+FLoanDoc_Value+
+ ',FLoanDoc_Enable='+FLoanDoc_Enable+
+ ',FUseProxy='+FUseProxy+
+ ',FC_DocNoList='+FC_DocNoList+
+ ',FC_DocNameList='+FC_DocNameList+
+ ',FFixFileList='+FFixFileList+
+ ',FIs_In_Wh='+FIs_In_Wh+
+ ',FOldCaseInfo='+FOldCaseInfo+
+ ',FPrintyn='+FPrintyn+
+ ',FIs_OldCase='+FIs_OldCase+
+ ',FCustDocYN='+FCustDocYN);
+ LogFile1.LogToFile(logTimeString+'FImgDPI='+IntToStr(FImgDPI)+
+ ',FScanColor='+ IntToStr(FScanColor)+
+ ',FFileSizeLimit='+ IntToStr(FFileSizeLimit)+
+ ',FCaseNoLength='+ IntToStr(FCaseNoLength)+
+ ',FImgDelete='+FImgDelete+
+ ',FIsExternal='+FIsExternal+
+ ',FWH_category='+FWH_category+
+ ',FCheck_main_form='+FCheck_main_form+
+ ',FMaxUploadSize='+FMaxUploadSize);
+
+end;
+
+procedure TCB_IMGPSScanX.Timer2Timer(Sender: TObject);
+begin
+ IF Panel22.Caption = ShowText+'......' Then
+ Panel22.Caption := ShowText
+ Else
+ Panel22.Caption := Panel22.Caption + '.';
+ Application.ProcessMessages;
+end;
+
+procedure TCB_IMGPSScanX.Set_mode(const Value: WideString);
+begin
+ FMode := UpperCase(Value);
+end;
+
+procedure TCB_IMGPSScanX.Set_rewrite(const Value: WideString);
+begin
+ FReWrite := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_url(const Value: WideString);
+begin
+ FUrl := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_userid(const Value: WideString);
+begin
+ FUserID := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_username(const Value: WideString);
+begin
+ FUserName := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_verify(const Value: WideString);
+begin
+ FVerify := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_language(const Value: WideString);
+begin
+ FLanguage := lowercase(Value);
+ if FLanguage='zh-tw' then
+ begin
+ FLanguage:='zh_tw'
+ end;
+ if FileExists(LngPath+'Language.lng') then
+ begin
+ InitialLanguage(Self); //載入多國語言
+ end;
+end;
+
+procedure TCB_IMGPSScanX.Set_modename(const Value: WideString);
+begin
+ FModeName := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_userunit(const Value: WideString);
+begin
+ FUserUnit := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_work_no(const Value: WideString);
+begin
+ FWork_no := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_loandoc_enable(const Value: WideString);
+begin
+ FLoanDoc_Enable := Value;
+ if FLoanDoc_Enable = 'Y' then
+ AddCredit1RG.Enabled := True;
+ if FLoanDoc_Enable = 'I' then
+ begin
+ AddCredit1RG.Visible := False;
+ Panel5.Visible := False;
+ end;
+end;
+
+procedure TCB_IMGPSScanX.Set_loandoc_value(const Value: WideString);
+begin
+ FLoanDoc_Value := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_useproxy(const Value: WideString);
+begin
+ FUseProxy := UpperCase(Value);
+ if FUseProxy = 'Y' then
+ UseProxy := True; //要不要用Proxy
+
+end;
+
+procedure TCB_IMGPSScanX.Set_c_docnamelist(const Value: WideString);
+begin
+ FC_DocNameList := Value;
+end;
+
+procedure TCB_IMGPSScanX.Set_is_in_wh(const Value: WideString);
+begin
+ FIs_In_Wh := UpperCase(Value);
+end;
+
+function TCB_IMGPSScanX.Get_c_docnamelist: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_is_in_wh: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_language: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_loandoc_enable: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_loandoc_value: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_mode: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_modename: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_rewrite: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_url: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_useproxy: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_userid: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_username: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_userunit: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_verify: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_work_no: WideString;
+begin
+
+end;
+
+function TCB_IMGPSScanX.Get_printyn: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_printyn(const Value: WideString);
+begin
+ FPrintyn := UpperCase(Value);
+end;
+
+function TCB_IMGPSScanX.Get_custdocyn: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_custdocyn(const Value: WideString);
+begin
+ FCustDocYN := UpperCase(Value);
+end;
+
+function TCB_IMGPSScanX.Get_imgdelete: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_imgdelete(const Value: WideString);
+begin
+ FImgDelete:=Value;
+end;
+
+function TCB_IMGPSScanX.Get_isExternal: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_isExternal(const Value: WideString);
+begin
+ FIsExternal:=Value;
+end;
+
+function TCB_IMGPSScanX.Get_WH_CATEGORY: WideString;
+begin
+
+end;
+
+procedure TCB_IMGPSScanX.Set_WH_CATEGORY(const Value: WideString);
+begin
+ FWH_category:=Value;
+end;
+
diff --git a/separate/scanImp/CB_IMGPSScanImp_Utils.ts b/separate/scanImp/CB_IMGPSScanImp_Utils.ts
new file mode 100644
index 0000000..a1ccd6e
--- /dev/null
+++ b/separate/scanImp/CB_IMGPSScanImp_Utils.ts
@@ -0,0 +1,59 @@
+import * as fs from 'fs'; import * as path from 'path';
+export enum TTransMode{tsHttp,tsFtp,tsNone} export enum TFtpProtocol{fpftp,fpftps} export type TImageFormat='ifBlackWhite'|'ifGray256'|'ifTrueColor'|'ifColor256';
+export class TStringList {
+ Strings:string[]=[]; get Count(){return this.Strings.length;}
+ Add(s:string){this.Strings.push(s);} Clear(){this.Strings=[];}
+ LoadFromFile(fp:string){if(fs.existsSync(fp))this.Strings=fs.readFileSync(fp,'utf8').split(/\r?\n/).filter(Boolean);}
+ SaveToFile(fp:string){fs.writeFileSync(fp,this.Strings.join('\n'),'utf8');}
+ Delete(idx:number){this.Strings.splice(idx,1);} Insert(idx:number,s:string){this.Strings.splice(idx,0,s);}
+ IndexOf(s:string){return this.Strings.indexOf(s);} get Text(){return this.Strings.join('\n');}
+ set Text(v:string){this.Strings=v.split('\n');} get CommaText(){return this.Strings.join(',');}
+ set CommaText(v:string){this.Strings=v.split(',');} Free(){} Sort(){this.Strings.sort();} Assign(s:TStringList){this.Strings=[...s.Strings];}
+}
+export function applyUtilsMixins(cls:any){
+ cls.prototype.GetCurrentVersionNo=function(){return "1.0.0";};
+ cls.prototype.DefinePropertyPages=function(){};
+ cls.prototype.InitExistImgList=function(cp:string){
+ let ST1=new TStringList(); this.ExistImgList.Clear();
+ ST1.LoadFromFile(path.join(cp,'Download','Context.dat'));
+ for(let i=0;i<ST1.Count;i++){ let m=this.LoadFileGetMD5(path.join(cp,'Download',ST1.Strings[i])); this.LogFile1.LogToFile(this.logTimeString()+path.join(cp,'Download',ST1.Strings[i])+',MD5='+m); this.ExistImgList.Add(m); }
+ this.LogFile1.LogToFile(this.logTimeString()+'ExistImgList.text'+this.ExistImgList.CommaText); ST1.Free();
+ };
+ cls.prototype.Initialize=function(){
+ ['Activate','Click','Create','DblClick','Deactivate','Destroy','KeyPress','MouseEnter','MouseLeave','Paint'].forEach(e=>this['On'+e]=this[e+'Event']?this[e+'Event'].bind(this):null);
+ this.MpsKey='fbim';this.Seg=3;this.Ext='.tif';this.SafePixel=20;this.CaseIDLength=16;this.FormIDLength=15;this.Bt=4;this.CropBarcode='CC';
+ };
+ cls.prototype.ISB1Enter=function(){this.ISB1.SetFocus();};
+ cls.prototype._Set_Font=function(v:any){this.Font=v;};
+ ['Active','AlignDisabled','AlignWithMargins','AutoScroll','AutoSize','AxBorderStyle','Caption','Color','DockSite','DoubleBuffered','DropTarget','Enabled','ExplicitHeight','ExplicitLeft','ExplicitTop','ExplicitWidth','Font','HelpFile','KeyPreview','MouseInClient','ParentCustomHint','ParentDoubleBuffered','PixelsPerInch','PopupMode','PrintScale','Scaled','ScreenSnap','SnapBuffer','UseDockManager','Visible','VisibleDockClientCount'].forEach(p=>{
+ cls.prototype['Get_'+p]=function(){return this[p];}; cls.prototype['Set_'+p]=function(v:any){this[p]=v;};
+ });
+ cls.prototype.LoadFileGetMD5=function(f:string){return "md5stub";};
+ cls.prototype.ISExistImg=function(f:string){return this.ExistImgList.IndexOf(this.LoadFileGetMD5(f))!==-1;};
+ cls.prototype.MemoInfoTransfer=function(m:string,s:string,id:TStringList,n:TStringList){
+ if(m==='ID'){for(let i=0;i<id.Count;i++)if(s===id.Strings[i])return n.Strings[i]; return '自行輸入';}
+ if(m==='NAME'){for(let i=0;i<n.Count;i++)if(s===n.Strings[i])return id.Strings[i]; return '00';} return '';
+ };
+ cls.prototype.SetSQLData=function(c:string,f:TStringList,t:TStringList){t.Clear();t.Add(c);for(let i=1;i<f.Count;i++)t.Add(f.Strings[i]);};
+ cls.prototype.GetSQLData=function(t:TStringList,c:string,no:number){
+ if(t.Count===0||no>=t.Count)return''; let cs=t.Strings[0].split(','),ts=t.Strings[no],ds=ts.split('!@!');
+ let idx=cs.indexOf(c); return(idx!==-1&&idx<ds.length)?ds[idx]:'';
+ };
+ cls.prototype.FindSQLData=function(t:TStringList,c:string,kc:string,ks:string,no:number,res:TStringList){
+ res.Clear(); if(!ks||t.Count<=1)return false;
+ let cl=c.split(','),kcl=kc.split(','),kl=ks.split(','),fidx=-1,found=false;
+ if(no===0){for(let i=1;i<t.Count;i++){let m=true;for(let n=0;n<kcl.length;n++)if(this.GetSQLData(t,kcl[n],i)!==kl[n]){m=false;break;}if(m){found=true;fidx=i;break;}}}
+ else{let m=true;for(let n=0;n<kcl.length;n++)if(t.Strings[no].indexOf('!@!'+kl[n]+'!@!')===-1){m=false;break;}if(m){found=true;fidx=no;}}
+ if(found)cl.forEach(co=>res.Add(co+','+this.GetSQLData(t,co,fidx))); return found;
+ };
+ cls.prototype.GetFindResult=function(c:string){for(let i=0;i<this.FindResult.Count;i++){let s=this.FindResult.Strings[i],idx=s.indexOf(',');if(idx>-1&&c===s.substring(0,idx))return s.substring(idx+1);}return'';};
+ cls.prototype.FileName2FormCode=function(f:string){let b=path.basename(f),v=b.indexOf('_'),v1=b.lastIndexOf('.');return(v>-1&&v1>v)?b.substring(v+1,v1):'';};
+ cls.prototype.FormCode2DocNo=function(fc:string){for(let i=0;i<this.FormID_List.Count;i++)if(this.FormID_List.Strings[i]===fc)return this.DocNo_List.Strings[i];return fc?fc.substring(0,8):'';};
+ cls.prototype.FormCode2Version=function(fc:string){return fc.substring(10,15);};
+ cls.prototype.FormCode2Page=function(fc:string){return fc.substring(8,10);};
+ cls.prototype.DocNoDir2DocNo=function(d:string){if(d!=='Attach'&&d!=='S_Attach'){let v=d.indexOf('(');if(v>0)return d.substring(0,v);}return d;};
+ cls.prototype.DocNo2DocNoDir=function(p:string,d:string){if(!d)return this.AttName;let i=0,id='';do{i++;id=d+'('+i+')';}while(fs.existsSync(path.join(p,id)));return id;};
+ cls.prototype.Add_Zoo=function(n:number,l:number){return n.toString().padStart(l,'0');};
+ cls.prototype.Str2Dir=function(p:string){if(!fs.existsSync(p))fs.mkdirSync(p,{recursive:true});};
+ cls.prototype._DelTree=function(p:string){if(fs.existsSync(p))fs.rmSync(p,{recursive:true,force:true});};
+}
diff --git a/split_pascal.js b/split_pascal.js
new file mode 100644
index 0000000..5db7fb6
--- /dev/null
+++ b/split_pascal.js
@@ -0,0 +1,98 @@
+const fs = require('fs');
+const path = require('path');
+
+// 檔案路徑設定
+const sourceFile = path.resolve(__dirname, 'CB_IMGPSScanImp.pas');
+const outDir = path.resolve(__dirname, 'separate', 'scanImp');
+
+if (!fs.existsSync(sourceFile)) {
+ console.error("找不到原始檔案:", sourceFile);
+ process.exit(1);
+}
+
+if (!fs.existsSync(outDir)) {
+ fs.mkdirSync(outDir, { recursive: true });
+}
+
+const content = fs.readFileSync(sourceFile, 'utf8');
+
+const implMatch = content.match(/\bimplementation\b/i);
+const initMatch = content.match(/\binitialization\b/i);
+
+if (!implMatch || !initMatch) {
+ console.error("無法在檔案中找到 implementation 或 initialization 區段。");
+ process.exit(1);
+}
+
+const headerPart = content.substring(0, implMatch.index + implMatch[0].length);
+let implPart = content.substring(implMatch.index + implMatch[0].length, initMatch.index);
+const footerPart = content.substring(initMatch.index);
+
+const usesMatch = implPart.match(/^\s*uses[\s\S]*?;/im);
+let usesClause = "";
+if (usesMatch) {
+ usesClause = usesMatch[0];
+ implPart = implPart.substring(usesMatch.index + usesMatch[0].length);
+}
+
+// 提取並保留不在方法內的實作開頭,例如 {$R *.DFM} 或是 { TCB_IMGPSScanX }
+const methodRegex = /^(?:procedure|function)\s+TCB_IMGPSScanX\./im;
+let otherImpl = "";
+const firstMethodMatch = implPart.match(methodRegex);
+
+if (firstMethodMatch) {
+ otherImpl = implPart.substring(0, firstMethodMatch.index);
+ implPart = implPart.substring(firstMethodMatch.index);
+}
+
+// 切割所有方法
+const methodSplitRegex = /(?=^(?:procedure|function)\s+TCB_IMGPSScanX\.)/im;
+const methods = implPart.split(methodSplitRegex).filter(m => m.trim().length > 0);
+
+const uiMethods = [];
+const scanMethods = [];
+const dataMethods = [];
+const utilMethods = [];
+
+methods.forEach(m => {
+ const nameMatch = m.match(/^(?:procedure|function)\s+TCB_IMGPSScanX\.([A-Za-z0-9_]+)/i);
+ if (nameMatch) {
+ const name = nameMatch[1].toLowerCase();
+ if (/(click|mouse|key|drag|scroll|event|menu|btn|form|node|tree|view|activate|paint|resize)/.test(name)) {
+ uiMethods.push(m);
+ } else if (/(scan|acquire|image|graphic|twain|dpi|color|deskew|rotate|crop|smooth|point)/.test(name)) {
+ scanMethods.push(m);
+ } else if (/(ftp|http|trans|load|sql|server|setinf|data|ask|log|file|path|zip|dir|docno|formid|case)/.test(name)) {
+ dataMethods.push(m);
+ } else {
+ utilMethods.push(m);
+ }
+ } else {
+ utilMethods.push(m);
+ }
+});
+
+fs.writeFileSync(path.join(outDir, 'CB_IMGPSScanImp_UI.pas'), uiMethods.join(''), 'utf8');
+fs.writeFileSync(path.join(outDir, 'CB_IMGPSScanImp_Scan.pas'), scanMethods.join(''), 'utf8');
+fs.writeFileSync(path.join(outDir, 'CB_IMGPSScanImp_Data.pas'), dataMethods.join(''), 'utf8');
+fs.writeFileSync(path.join(outDir, 'CB_IMGPSScanImp_Utils.pas'), utilMethods.join(''), 'utf8');
+
+const mainFile = [
+ headerPart,
+ usesClause,
+ otherImpl,
+ "{$I CB_IMGPSScanImp_UI.pas}",
+ "{$I CB_IMGPSScanImp_Scan.pas}",
+ "{$I CB_IMGPSScanImp_Data.pas}",
+ "{$I CB_IMGPSScanImp_Utils.pas}",
+ footerPart
+].join('');
+
+fs.writeFileSync(path.join(outDir, 'CB_IMGPSScanImp_Main.pas'), mainFile, 'utf8');
+
+console.log("拆分完成!產生的五個檔案如下:");
+console.log("1. CB_IMGPSScanImp_Main.pas (主結構與引用)");
+console.log("2. CB_IMGPSScanImp_UI.pas (UI事件相關:", uiMethods.length, "個方法)");
+console.log("3. CB_IMGPSScanImp_Scan.pas (掃描影像相關:", scanMethods.length, "個方法)");
+console.log("4. CB_IMGPSScanImp_Data.pas (資料存取與網路傳輸:", dataMethods.length, "個方法)");
+console.log("5. CB_IMGPSScanImp_Utils.pas (工具與其他邏輯:", utilMethods.length, "個方法)");
--
Gitblit v1.8.0