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;
|
}
|
}
|