import { AbsRowData, RowData, TableData } from '@b2b/hq_table'; import { TableConstants, TableRequestClient } from '@b2c/lib_baseui'; import { RequestHelper, StuffTableStruct } from '@kernel/lib_communication'; import { QuoteCustomSettingManager, StandardPriceType, StandardPriceTypeHelper, applyStandardPriceToTableData, } from 'biz_quote'; import { CardData, PickContractItem, PickTabData, } from '../../ai-pick/AiPickModels'; import { getUniqueContracts } from '../../ai-pick/AiPickUtils'; const FRAME_ID = 2201; const PAGE_ID = 4106; const FIELD_IDS: number[] = [ TableConstants.DATA_ID_CODE_4, TableConstants.DATA_ID_PRICE, TableConstants.DATA_ID_ZF, TableConstants.DATA_ID_ZD, TableConstants.DATA_ID_MARKET, TableConstants.DATA_ID_MARKET_OLD, StandardPriceTypeHelper.FIELD_ZUO_SHOU, StandardPriceTypeHelper.FIELD_JIN_KAI, StandardPriceTypeHelper.FIELD_ZUO_JIE, ]; interface AiPickQuote { price?: number; priceChg?: number; } export type AiPickCardDataListener = (cardData: CardData) => void; class AiPickTableRequestClient extends TableRequestClient { private requestParams: string; private sourceCardData: CardData; private listener: AiPickCardDataListener; constructor( requestParams: string, sourceCardData: CardData, listener: AiPickCardDataListener, ) { super(FRAME_ID, PAGE_ID, [], null, undefined); this.requestParams = requestParams; this.sourceCardData = sourceCardData; this.listener = listener; this.setSubscribeIds(FIELD_IDS); } protected doRequest(): void { RequestHelper.getHqManager() .addRequestStructToBuff(this.frameId, this.pageId, this.getInstanceId(), this.requestParams); RequestHelper.build().base(this.frameId, this.pageId, this, this.requestParams).request(); } protected afterParserModel(tableData: TableData, structData: StuffTableStruct): void { applyStandardPriceToTableData(tableData, structData, FIELD_IDS); const quoteMap: Map = this.toQuoteMap(tableData); const nextCardData: CardData = this.mergeQuoteData(quoteMap); this.sourceCardData = nextCardData; this.listener(nextCardData); } private toQuoteMap(tableData: TableData): Map { const quoteMap: Map = new Map(); if (!tableData.tableRows) { return quoteMap; } tableData.tableRows.forEach((row: AbsRowData): void => { if (!(row instanceof RowData)) { return; } const codeValue = row.originalData.get(TableConstants.DATA_ID_CODE_4); const marketValue = row.originalData.get(TableConstants.DATA_ID_MARKET); if (codeValue === undefined || marketValue === undefined) { return; } const quote: AiPickQuote = { price: this.getNumber(row, TableConstants.DATA_ID_PRICE), priceChg: this.getNumber(row, TableConstants.DATA_ID_ZF), }; quoteMap.set(`${codeValue}_${marketValue}`, quote); }); return quoteMap; } private mergeQuoteData(quoteMap: Map): CardData { const tabs: PickTabData[] = this.sourceCardData.tabs.map((tab: PickTabData): PickTabData => { const items: PickContractItem[] = tab.items.map((item: PickContractItem): PickContractItem => { const quote: AiPickQuote | undefined = quoteMap.get(`${item.contract}_${item.market}`); const nextItem: PickContractItem = { contract: item.contract, market: item.market, name: item.name, price: quote?.price ?? item.price, priceChg: quote?.priceChg ?? item.priceChg, isMain: item.isMain, extraFields: item.extraFields, }; return nextItem; }); const nextTab: PickTabData = { strategy: tab.strategy, items: items, keysList: tab.keysList, fieldList: tab.fieldList, }; return nextTab; }); const nextCardData: CardData = { tabs: tabs }; return nextCardData; } private getNumber(row: RowData, fieldId: number): number | undefined { const value = row.originalData.get(fieldId); if (typeof value === 'number') { return value; } if (typeof value === 'string' && value !== '' && value !== '--') { const result: number = parseFloat(value); return Number.isNaN(result) ? undefined : result; } return undefined; } } export class AiPickHqRequestClient { private static readonly instance: AiPickHqRequestClient = new AiPickHqRequestClient(); private constructor() { } static getInstance(): AiPickHqRequestClient { return AiPickHqRequestClient.instance; } subscribeHq(cardData: CardData, listener: AiPickCardDataListener): () => void { const contracts: PickContractItem[] = getUniqueContracts(cardData); if (contracts.length === 0) { return (): void => { }; } const requestParams: string = this.buildRequestParams(contracts); const requestClient: AiPickTableRequestClient = new AiPickTableRequestClient(requestParams, cardData, listener); requestClient.request(0, contracts.length); return (): void => { requestClient.release(true); }; } private buildRequestParams(contracts: PickContractItem[]): string { const computeMode: StandardPriceType = QuoteCustomSettingManager.getInstance().getStandardPriceType(); return `\r\nsortid=-1\r\n` + `sortorder=0\r\n` + `push=1\r\n` + `dataitem=${FIELD_IDS.map((fieldId: number): string => `${fieldId},`).join('')}\r\n` + `codelist=${this.formatCodeList(contracts)}\r\n` + `update=1\r\n` + `computemode=${computeMode}\r\n` + `scenario=qht_qihuo_sort\r\n` + `precision=1\r\n` + `pushtime=2.5\r\n`; } private formatCodeList(contracts: PickContractItem[]): string { const markets: string[] = []; const codeGroups: string[][] = []; contracts.forEach((contract: PickContractItem): void => { const marketIndex: number = markets.indexOf(contract.market); if (marketIndex >= 0) { codeGroups[marketIndex].push(contract.contract); } else { markets.push(contract.market); codeGroups.push([contract.contract]); } }); return markets.map((market: string, index: number): string => `${market}(${codeGroups[index].map((code: string): string => `${code},`).join('')});` ).join(''); } }