ohayolibs
Version:
Ohayo is a set of essential modules for ohayojp.
217 lines (198 loc) • 6.31 kB
text/typescript
import { Injectable, OnDestroy } from '@angular/core';
import { OhayoConfigService, OhayoLodopConfig, LazyService } from '@ohayo/util';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { Observable, of, Subject } from 'rxjs';
import { Lodop, LodopPrintResult, LodopResult } from './lodop.types';
export class LodopService implements OnDestroy {
private defaultConfig: OhayoLodopConfig;
private _cog: OhayoLodopConfig;
private pending = false;
private _lodop: Lodop | null = null;
private _init = new Subject<LodopResult>();
private _events = new Subject<LodopPrintResult>();
private printBuffer: any[] = [];
constructor(private scriptSrv: LazyService, configSrv: OhayoConfigService) {
this.defaultConfig = configSrv.merge('lodop', {
url: '//localhost:8443/CLodopfuncs.js',
name: 'CLODOP',
companyName: '',
checkMaxCount: 100,
})!;
this.cog = this.defaultConfig;
}
/**
* 获取或重新设置配置
*
* **注:**重新设置会倒置重新加载脚本资源
*/
get cog(): OhayoLodopConfig {
return this._cog;
}
set cog(value: OhayoLodopConfig) {
this._cog = {
...this.defaultConfig,
...value,
};
}
/** 事件变更通知 */
get events(): Observable<LodopPrintResult> {
return this._events.asObservable();
}
/** 获取 lodop 对象 */
get lodop(): Observable<LodopResult> {
if (this._lodop) return of({ ok: true, lodop: this._lodop } as LodopResult);
if (this.pending) return this._init.asObservable();
this.request();
return this._init.asObservable();
}
/** 获取打印机列表 */
get printer(): string[] {
this.check();
const ret: string[] = [];
const count = this._lodop!.GET_PRINTER_COUNT();
for (let index = 0; index < count; index++) {
ret.push(this._lodop!.GET_PRINTER_NAME(index));
}
return ret;
}
private check(): void {
if (!this._lodop) throw new Error(`请务必先调用 lodop 获取对象`);
}
private request(): void {
this.pending = true;
const url = `${this.cog.url}?name=${this.cog.name}`;
let checkMaxCount = this.cog.checkMaxCount as number;
const onResolve = (status: NzSafeAny, error?: {}) => {
this._init.next({
ok: status === 'ok',
status,
error,
lodop: this._lodop!,
});
};
const checkStatus = () => {
--checkMaxCount;
if (this._lodop!.webskt && this._lodop!.webskt.readyState === 1) {
onResolve('ok');
} else {
if (checkMaxCount < 0) {
onResolve('check-limit');
return;
}
setTimeout(() => checkStatus(), 100);
}
};
this.scriptSrv.loadScript(url).then((res: NzSafeAny) => {
if (res.status !== 'ok') {
this.pending = false;
onResolve('script-load-error', res[0]);
return;
}
const win = window as NzSafeAny;
if (win.hasOwnProperty(this.cog.name!)) {
this._lodop = win[this.cog.name!] as Lodop;
}
if (this._lodop === null) {
onResolve('load-variable-name-error', { name: this.cog.name });
return;
}
this._lodop.SET_LICENSES(this.cog.companyName!, this.cog.license!, this.cog.licenseA, this.cog.licenseB);
checkStatus();
});
}
/** 重置 lodop 对象 */
reset(): void {
this._lodop = null;
this.pending = false;
this.request();
}
/**
* 附加代码至 `lodop` 对象上,字符串类支持 `{{key}}` 的动态参数
*
* **注:** 代码是指打印设计所产生字符串数据
*
* @param code 代码
* @param contextObj 动态参数上下文对象
* @param parser 自定义解析表达式,默认:`/LODOP\.([^(]+)\(([^\n]+)?\);/i`
*/
attachCode(code: string, contextObj?: NzSafeAny, parser?: RegExp): void {
this.check();
if (!parser) parser = /LODOP\.([^(]+)\(([^\n]+)?\);/i;
code.split('\n').forEach(line => {
const res = parser!.exec(line.trim());
if (!res) return;
const fn = this._lodop![res[1]];
if (fn) {
let arr: any[] | null = null;
try {
// tslint:disable-next-line: function-constructor
const fakeFn = new Function(`return [${res[2]}]`);
arr = fakeFn();
} catch { }
if (arr != null && Array.isArray(arr) && contextObj) {
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] === 'string') {
arr[i] = (arr[i] as string).replace(/{{(.*?)}}/g, (_match, key) => contextObj[key.trim()] || '');
}
}
}
fn.apply(this._lodop, arr!);
}
});
}
/**
* 打开打印设计关闭后自动返回代码
*
* **注:** 自动监听 `On_Return` 事件,运行后会移除
*/
design(): Promise<string> {
this.check();
const tid = this._lodop!.PRINT_DESIGN();
return new Promise(resolve => {
this._lodop!.On_Return = (taskID: string, value: boolean | string) => {
if (tid !== taskID) return;
this._lodop!.On_Return = null;
resolve('' + value);
};
});
}
private printDo(): void {
const data = this.printBuffer.shift();
if (!data) return;
this.attachCode(data.code, data.item, data.parser);
const tid = this._lodop!.PRINT();
this._lodop!.On_Return = (taskID: string, value: boolean | string) => {
if (tid !== taskID) return;
this._lodop!.On_Return = null;
this._events.next({
ok: value === true,
error: value === true ? null : value,
...data,
});
this.printDo();
};
}
/**
* 立即打印,一般用于批量套打
*
* @param code 代码
* @param contextObj 动态参数上下文对象
* @param parser 自定义解析表达式,默认:`/LODOP\.([^(]+)\(([^\n]+)?\);/i`
*/
print(code: string, contextObj: {} | Array<{}>, parser?: RegExp): void {
this.check();
if (contextObj) {
this.printBuffer.push(
...(Array.isArray(contextObj) ? contextObj : [contextObj]).map(item => {
return { code, parser, item };
}),
);
}
this.printDo();
}
ngOnDestroy(): void {
this._init.unsubscribe();
this._events.unsubscribe();
}
}