fix(ai-pick): complete quote handling and component organization
This commit is contained in:
@@ -18,7 +18,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
EMPTY_IMAGE_DARK,
|
EMPTY_IMAGE_DARK,
|
||||||
EMPTY_IMAGE_LIGHT,
|
EMPTY_IMAGE_LIGHT,
|
||||||
MAX_ITEMS,
|
|
||||||
} from './AiPickConstant';
|
} from './AiPickConstant';
|
||||||
import { AllCardsCard } from '../node/model/AiDiagnosisNodeModel';
|
import { AllCardsCard } from '../node/model/AiDiagnosisNodeModel';
|
||||||
import { RouterUtil } from '../util/RouterUtil';
|
import { RouterUtil } from '../util/RouterUtil';
|
||||||
@@ -28,36 +27,36 @@ interface StrategyDescParams {
|
|||||||
tabIdx: number;
|
tabIdx: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TAB_BAR_HEIGHT = 30;
|
|
||||||
const STRATEGY_DESC_HEIGHT = 86;
|
|
||||||
const TABLE_HEADER_HEIGHT = 40;
|
|
||||||
const TABLE_ROW_HEIGHT = 45;
|
|
||||||
const TABLE_HEIGHT = TABLE_HEADER_HEIGHT + TABLE_ROW_HEIGHT * MAX_ITEMS;
|
|
||||||
const CUSTOM_STRATEGY_HEIGHT = 30;
|
|
||||||
const MAIN_CONTENT_HEIGHT =
|
|
||||||
TAB_BAR_HEIGHT + STRATEGY_DESC_HEIGHT + TABLE_HEIGHT + CUSTOM_STRATEGY_HEIGHT;
|
|
||||||
const NO_CONTRACT_HEIGHT = STRATEGY_DESC_HEIGHT + TABLE_HEIGHT;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export struct AiPickNodeComponent {
|
export struct AiPickNodeComponent {
|
||||||
|
// 外部状态
|
||||||
@Link @Watch('onRefreshTriggerChange') refreshTrigger: number;
|
@Link @Watch('onRefreshTriggerChange') refreshTrigger: number;
|
||||||
@Consume('firstPageVisible') @Watch('onFirstPageVisibleChange')
|
@Consume('firstPageVisible') @Watch('onFirstPageVisibleChange')
|
||||||
firstPageVisible: boolean = true;
|
firstPageVisible: boolean = true;
|
||||||
@StorageProp(enableDarkMode) isDarkMode: boolean = false;
|
@StorageProp(enableDarkMode) isDarkMode: boolean = false;
|
||||||
|
|
||||||
|
// 卡片业务数据
|
||||||
@State cardConfig: AllCardsCard | undefined = undefined;
|
@State cardConfig: AllCardsCard | undefined = undefined;
|
||||||
@State cardData: CardData = { tabs: [] };
|
@State cardData: CardData = { tabs: [] };
|
||||||
|
// 区分加载中和暂无数据
|
||||||
@State dataReady: boolean = false;
|
@State dataReady: boolean = false;
|
||||||
|
|
||||||
|
// Tab 状态及滚动区域
|
||||||
@State tabIdx: number = 0;
|
@State tabIdx: number = 0;
|
||||||
@State tabViewportWidth: number = 0;
|
@State tabViewportWidth: number = 0;
|
||||||
@State tabContentWidth: number = 0;
|
@State tabContentWidth: number = 0;
|
||||||
@State tabScrollOffset: number = 0;
|
@State tabScrollOffset: number = 0;
|
||||||
|
|
||||||
|
// 弹层状态
|
||||||
@State showExplainSheet: boolean = false;
|
@State showExplainSheet: boolean = false;
|
||||||
|
|
||||||
|
// 生命周期与异步请求状态
|
||||||
private isComponentActive: boolean = false;
|
private isComponentActive: boolean = false;
|
||||||
private dataRequestVersion: number = 0;
|
private dataRequestVersion: number = 0;
|
||||||
private hqSubscriptionVersion: number = 0;
|
|
||||||
|
// 行情订阅与事件状态
|
||||||
private hqUnsubscribe: (() => void) | undefined;
|
private hqUnsubscribe: (() => void) | undefined;
|
||||||
|
private hqSubscriptionVersion: number = 0;
|
||||||
private isTcpEventSubscribed: boolean = false;
|
private isTcpEventSubscribed: boolean = false;
|
||||||
private tcpReconnectListener = (): void => {
|
private tcpReconnectListener = (): void => {
|
||||||
if (!this.canUseHq()) {
|
if (!this.canUseHq()) {
|
||||||
@@ -65,11 +64,13 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
setTimeout((): void => {
|
setTimeout((): void => {
|
||||||
if (this.canUseHq()) {
|
if (this.canUseHq()) {
|
||||||
this.restartSubscription();
|
this.restartCurrentSubscription();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==================== 组件生命周期 ====================
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
this.isComponentActive = true;
|
this.isComponentActive = true;
|
||||||
this.updateCardConfig();
|
this.updateCardConfig();
|
||||||
@@ -86,6 +87,14 @@ export struct AiPickNodeComponent {
|
|||||||
this.unSubscribeTcpNetStatus();
|
this.unSubscribeTcpNetStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 配置与刷新 ====================
|
||||||
|
|
||||||
|
// 从首页统一卡片配置中读取 AI Pick 配置。
|
||||||
|
private updateCardConfig(): void {
|
||||||
|
this.cardConfig = AiPickDataFetcher.getInstance().fetchCardConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
// refreshTrigger 变化时重新获取策略和合约,并在请求完成后重建行情订阅。
|
||||||
onRefreshTriggerChange(): void {
|
onRefreshTriggerChange(): void {
|
||||||
if (!this.isComponentActive) {
|
if (!this.isComponentActive) {
|
||||||
return;
|
return;
|
||||||
@@ -94,6 +103,9 @@ export struct AiPickNodeComponent {
|
|||||||
this.updateCardData();
|
this.updateCardData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 可见性与 TCP 重连 ====================
|
||||||
|
|
||||||
|
// 页面不可见时停止行情;恢复可见后使用已有数据重建订阅。
|
||||||
onFirstPageVisibleChange(): void {
|
onFirstPageVisibleChange(): void {
|
||||||
if (!this.isComponentActive) {
|
if (!this.isComponentActive) {
|
||||||
return;
|
return;
|
||||||
@@ -111,10 +123,43 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateCardConfig(): void {
|
private subscribeTcpNetStatus(): void {
|
||||||
this.cardConfig = AiPickDataFetcher.getInstance().fetchCardConfig();
|
if (this.isTcpEventSubscribed || !this.canUseHq()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isTcpEventSubscribed = true;
|
||||||
|
emitter.on(
|
||||||
|
{ eventId: EmitterConstants.NETWORK_TCP_RECONNECT },
|
||||||
|
this.tcpReconnectListener,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unSubscribeTcpNetStatus(): void {
|
||||||
|
if (!this.isTcpEventSubscribed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isTcpEventSubscribed = false;
|
||||||
|
emitter.off(
|
||||||
|
EmitterConstants.NETWORK_TCP_RECONNECT,
|
||||||
|
this.tcpReconnectListener,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收到 TCP 重连事件后,仅在页面可见时重建原合约订阅。
|
||||||
|
private restartCurrentSubscription(): void {
|
||||||
|
if (!this.canUseHq()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.cardData.tabs.length > 0) {
|
||||||
|
this.subscribeHq();
|
||||||
|
} else if (this.dataReady) {
|
||||||
|
this.updateCardData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 数据请求与行情订阅 ====================
|
||||||
|
|
||||||
|
// 请求所有策略和合约;刷新成功后保留已有行情值,避免列表短暂回退到占位状态。
|
||||||
private async updateCardData(): Promise<void> {
|
private async updateCardData(): Promise<void> {
|
||||||
if (!this.isComponentActive) {
|
if (!this.isComponentActive) {
|
||||||
return;
|
return;
|
||||||
@@ -151,6 +196,7 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTP 刷新时按“合约 + 市场”复用旧行情,等待新订阅首包覆盖。
|
||||||
private mergeCachedQuotes(tabs: PickTabData[]): PickTabData[] {
|
private mergeCachedQuotes(tabs: PickTabData[]): PickTabData[] {
|
||||||
const cachedContracts: PickContractItem[] = getUniqueContracts(this.cardData);
|
const cachedContracts: PickContractItem[] = getUniqueContracts(this.cardData);
|
||||||
const cachedMap: Map<string, PickContractItem> =
|
const cachedMap: Map<string, PickContractItem> =
|
||||||
@@ -184,6 +230,7 @@ export struct AiPickNodeComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AI Pick 一次订阅所有 Tab 的去重合约,推送后合并回完整卡片数据。
|
||||||
private subscribeHq(): void {
|
private subscribeHq(): void {
|
||||||
this.stopSubscribeHq();
|
this.stopSubscribeHq();
|
||||||
if (!this.canUseHq() || this.cardData.tabs.length === 0) {
|
if (!this.canUseHq() || this.cardData.tabs.length === 0) {
|
||||||
@@ -209,36 +256,6 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private restartSubscription(): void {
|
|
||||||
if (this.cardData.tabs.length > 0) {
|
|
||||||
this.subscribeHq();
|
|
||||||
} else if (this.dataReady) {
|
|
||||||
this.updateCardData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private subscribeTcpNetStatus(): void {
|
|
||||||
if (this.isTcpEventSubscribed || !this.canUseHq()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isTcpEventSubscribed = true;
|
|
||||||
emitter.on(
|
|
||||||
{ eventId: EmitterConstants.NETWORK_TCP_RECONNECT },
|
|
||||||
this.tcpReconnectListener,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private unSubscribeTcpNetStatus(): void {
|
|
||||||
if (!this.isTcpEventSubscribed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.isTcpEventSubscribed = false;
|
|
||||||
emitter.off(
|
|
||||||
EmitterConstants.NETWORK_TCP_RECONNECT,
|
|
||||||
this.tcpReconnectListener,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private canUseHq(): boolean {
|
private canUseHq(): boolean {
|
||||||
return this.isComponentActive && this.firstPageVisible;
|
return this.isComponentActive && this.firstPageVisible;
|
||||||
}
|
}
|
||||||
@@ -247,6 +264,63 @@ export struct AiPickNodeComponent {
|
|||||||
return this.isComponentActive && requestVersion === this.dataRequestVersion;
|
return this.isComponentActive && requestVersion === this.dataRequestVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 页面跳转 ====================
|
||||||
|
|
||||||
|
// 跳转客户端行情页,并保持合约、市场和名称列表顺序一致。
|
||||||
|
private jumpToDetail(item: PickContractItem): void {
|
||||||
|
const contracts: PickContractItem[] = getUniqueContracts(this.cardData);
|
||||||
|
const codeList: string =
|
||||||
|
contracts.map((contract: PickContractItem): string => contract.contract).join(',');
|
||||||
|
const marketIdList: string =
|
||||||
|
contracts.map((contract: PickContractItem): string => contract.market).join(',');
|
||||||
|
const nameList: string =
|
||||||
|
contracts.map((contract: PickContractItem): string => contract.name).join(',');
|
||||||
|
jumpToQuote(item.contract, item.market, codeList, marketIdList, nameList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到卡片配置中的标题地址。
|
||||||
|
private jumpToCardTitle(): void {
|
||||||
|
const jumpUrl: string =
|
||||||
|
this.cardConfig?.card_url.android || this.cardConfig?.card_url.ios || '';
|
||||||
|
RouterUtil.jumpPage(jumpUrl, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转 AI 策略定制首页。
|
||||||
|
private jumpToNewHome(): void {
|
||||||
|
const pageUrl: string =
|
||||||
|
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-home.html?sync=1';
|
||||||
|
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转策略详情页。
|
||||||
|
private jumpToStrategyDetail(strategy: PickStrategy): void {
|
||||||
|
const pageUrl: string =
|
||||||
|
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-detail.html' +
|
||||||
|
`?id=${strategy.id}&type=${strategy.periodType}` +
|
||||||
|
`&name=${encodeURIComponent(strategy.name)}`;
|
||||||
|
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转策略标签页。
|
||||||
|
private jumpToLabel(strategy: PickStrategy, label: string): void {
|
||||||
|
const pageUrl: string =
|
||||||
|
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-label.html' +
|
||||||
|
`?id=${strategy.id}&type=${strategy.periodType}` +
|
||||||
|
`&label=${encodeURIComponent(label)}`;
|
||||||
|
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用宿主统一的 client.html 协议包装 H5 地址。
|
||||||
|
private buildClientUrl(pageUrl: string): string {
|
||||||
|
const title: string =
|
||||||
|
this.cardConfig?.card_title.value ||
|
||||||
|
getResourceString(getContext(this), $r('app.string.ai_pick_title'));
|
||||||
|
return 'client.html?action=ymtz^ishiddenbar=1^mode=new^webid=2804^' +
|
||||||
|
`url=${pageUrl}^title=${title}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== UI 构建 ====================
|
||||||
|
|
||||||
private showTabGradient(): boolean {
|
private showTabGradient(): boolean {
|
||||||
const maxOffset: number = this.tabContentWidth - this.tabViewportWidth;
|
const maxOffset: number = this.tabContentWidth - this.tabViewportWidth;
|
||||||
return maxOffset > 0 && this.tabScrollOffset < maxOffset;
|
return maxOffset > 0 && this.tabScrollOffset < maxOffset;
|
||||||
@@ -389,7 +463,7 @@ export struct AiPickNodeComponent {
|
|||||||
this.buildCustomStrategy()
|
this.buildCustomStrategy()
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(MAIN_CONTENT_HEIGHT)
|
.height(321)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@@ -409,7 +483,7 @@ export struct AiPickNodeComponent {
|
|||||||
.constraintSize({ minWidth: 66 })
|
.constraintSize({ minWidth: 66 })
|
||||||
.maxLines(1)
|
.maxLines(1)
|
||||||
.textAlign(TextAlign.Center)
|
.textAlign(TextAlign.Center)
|
||||||
.height(TAB_BAR_HEIGHT)
|
.height(30)
|
||||||
.padding({ left: 8, right: 8 })
|
.padding({ left: 8, right: 8 })
|
||||||
.borderRadius(4)
|
.borderRadius(4)
|
||||||
.backgroundColor(this.tabIdx === index
|
.backgroundColor(this.tabIdx === index
|
||||||
@@ -426,7 +500,7 @@ export struct AiPickNodeComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(TAB_BAR_HEIGHT)
|
.height(30)
|
||||||
.padding({ right: 10 })
|
.padding({ right: 10 })
|
||||||
.scrollable(ScrollDirection.Horizontal)
|
.scrollable(ScrollDirection.Horizontal)
|
||||||
.scrollBar(BarState.Off)
|
.scrollBar(BarState.Off)
|
||||||
@@ -438,7 +512,7 @@ export struct AiPickNodeComponent {
|
|||||||
if (this.showTabGradient()) {
|
if (this.showTabGradient()) {
|
||||||
Row()
|
Row()
|
||||||
.width(24)
|
.width(24)
|
||||||
.height(TAB_BAR_HEIGHT)
|
.height(30)
|
||||||
.linearGradient({
|
.linearGradient({
|
||||||
angle: 90,
|
angle: 90,
|
||||||
colors: [
|
colors: [
|
||||||
@@ -450,7 +524,7 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(TAB_BAR_HEIGHT)
|
.height(30)
|
||||||
.onAreaChange((_oldValue: Area, newValue: Area) => {
|
.onAreaChange((_oldValue: Area, newValue: Area) => {
|
||||||
this.tabViewportWidth = Number(newValue.width);
|
this.tabViewportWidth = Number(newValue.width);
|
||||||
})
|
})
|
||||||
@@ -526,7 +600,7 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(STRATEGY_DESC_HEIGHT)
|
.height(86)
|
||||||
.padding({ top: 10, bottom: 10 })
|
.padding({ top: 10, bottom: 10 })
|
||||||
.alignItems(VerticalAlign.Top)
|
.alignItems(VerticalAlign.Top)
|
||||||
}
|
}
|
||||||
@@ -551,7 +625,7 @@ export struct AiPickNodeComponent {
|
|||||||
.textAlign(TextAlign.End)
|
.textAlign(TextAlign.End)
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(TABLE_HEADER_HEIGHT)
|
.height(40)
|
||||||
|
|
||||||
ForEach(
|
ForEach(
|
||||||
this.cardData.tabs[this.tabIdx].items,
|
this.cardData.tabs[this.tabIdx].items,
|
||||||
@@ -563,7 +637,7 @@ export struct AiPickNodeComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(TABLE_HEIGHT)
|
.height(175)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@@ -629,7 +703,7 @@ export struct AiPickNodeComponent {
|
|||||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(TABLE_ROW_HEIGHT)
|
.height(45)
|
||||||
.alignItems(VerticalAlign.Center)
|
.alignItems(VerticalAlign.Center)
|
||||||
.border({
|
.border({
|
||||||
width: { top: 1 },
|
width: { top: 1 },
|
||||||
@@ -653,7 +727,7 @@ export struct AiPickNodeComponent {
|
|||||||
.fillColor($r('app.color.elements_icon_tertiary'))
|
.fillColor($r('app.color.elements_icon_tertiary'))
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(CUSTOM_STRATEGY_HEIGHT)
|
.height(30)
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
.alignItems(VerticalAlign.Center)
|
.alignItems(VerticalAlign.Center)
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
@@ -679,7 +753,7 @@ export struct AiPickNodeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(MAIN_CONTENT_HEIGHT)
|
.height(321)
|
||||||
.alignItems(HorizontalAlign.Center)
|
.alignItems(HorizontalAlign.Center)
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
}
|
}
|
||||||
@@ -695,55 +769,9 @@ export struct AiPickNodeComponent {
|
|||||||
.fontColor($r('app.color.elements_text_tertiary'))
|
.fontColor($r('app.color.elements_text_tertiary'))
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height(NO_CONTRACT_HEIGHT)
|
.height(261)
|
||||||
.alignItems(HorizontalAlign.Center)
|
.alignItems(HorizontalAlign.Center)
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
}
|
}
|
||||||
|
|
||||||
private jumpToDetail(item: PickContractItem): void {
|
|
||||||
const contracts: PickContractItem[] = getUniqueContracts(this.cardData);
|
|
||||||
const codeList: string =
|
|
||||||
contracts.map((contract: PickContractItem): string => contract.contract).join(',');
|
|
||||||
const marketIdList: string =
|
|
||||||
contracts.map((contract: PickContractItem): string => contract.market).join(',');
|
|
||||||
const nameList: string =
|
|
||||||
contracts.map((contract: PickContractItem): string => contract.name).join(',');
|
|
||||||
jumpToQuote(item.contract, item.market, codeList, marketIdList, nameList);
|
|
||||||
}
|
|
||||||
|
|
||||||
private jumpToCardTitle(): void {
|
|
||||||
const jumpUrl: string =
|
|
||||||
this.cardConfig?.card_url.android || this.cardConfig?.card_url.ios || '';
|
|
||||||
RouterUtil.jumpPage(jumpUrl, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private jumpToNewHome(): void {
|
|
||||||
const pageUrl: string =
|
|
||||||
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-home.html?sync=1';
|
|
||||||
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private jumpToStrategyDetail(strategy: PickStrategy): void {
|
|
||||||
const pageUrl: string =
|
|
||||||
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-detail.html' +
|
|
||||||
`?id=${strategy.id}&type=${strategy.periodType}` +
|
|
||||||
`&name=${encodeURIComponent(strategy.name)}`;
|
|
||||||
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private jumpToLabel(strategy: PickStrategy, label: string): void {
|
|
||||||
const pageUrl: string =
|
|
||||||
'https://fupage.10jqka.com.cn/ai-web/ai-diagnosis-label.html' +
|
|
||||||
`?id=${strategy.id}&type=${strategy.periodType}` +
|
|
||||||
`&label=${encodeURIComponent(label)}`;
|
|
||||||
RouterUtil.jumpPage(this.buildClientUrl(pageUrl), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildClientUrl(pageUrl: string): string {
|
|
||||||
const title: string =
|
|
||||||
this.cardConfig?.card_title.value ||
|
|
||||||
getResourceString(getContext(this), $r('app.string.ai_pick_title'));
|
|
||||||
return 'client.html?action=ymtz^ishiddenbar=1^mode=new^webid=2804^' +
|
|
||||||
`url=${pageUrl}^title=${title}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,31 @@
|
|||||||
import { AbsRowData, RowData, TableData } from '@b2b/hq_table';
|
import { AbsRowData, RowData, TableData } from '@b2b/hq_table';
|
||||||
import { TableRequestClient } from '@b2c/lib_baseui';
|
import { TableConstants, TableRequestClient } from '@b2c/lib_baseui';
|
||||||
import { RequestHelper, StuffTableStruct } from '@kernel/lib_communication';
|
import { RequestHelper, StuffTableStruct } from '@kernel/lib_communication';
|
||||||
|
import {
|
||||||
|
QuoteCustomSettingManager,
|
||||||
|
StandardPriceType,
|
||||||
|
StandardPriceTypeHelper,
|
||||||
|
applyStandardPriceToTableData,
|
||||||
|
} from 'biz_quote';
|
||||||
import {
|
import {
|
||||||
CardData,
|
CardData,
|
||||||
PickContractItem,
|
PickContractItem,
|
||||||
PickTabData,
|
PickTabData,
|
||||||
} from '../../ai-pick/AiPickModels';
|
} from '../../ai-pick/AiPickModels';
|
||||||
import { getUniqueContracts } from '../../ai-pick/AiPickUtils';
|
import { getUniqueContracts } from '../../ai-pick/AiPickUtils';
|
||||||
import { TableConstants } from '../../market-ranking/TableConstants';
|
|
||||||
|
|
||||||
const FRAME_ID = 2201;
|
const FRAME_ID = 2201;
|
||||||
const PAGE_ID = 4106;
|
const PAGE_ID = 4106;
|
||||||
const FIELD_IDS: number[] = [
|
const FIELD_IDS: number[] = [
|
||||||
TableConstants.DATA_ID_CODE_4,
|
TableConstants.DATA_ID_CODE_4,
|
||||||
TableConstants.DATA_ID_PRICE,
|
TableConstants.DATA_ID_PRICE,
|
||||||
|
TableConstants.DATA_ID_ZF,
|
||||||
|
TableConstants.DATA_ID_ZD,
|
||||||
TableConstants.DATA_ID_MARKET,
|
TableConstants.DATA_ID_MARKET,
|
||||||
TableConstants.DATA_ID_ZF_YTD,
|
TableConstants.DATA_ID_MARKET_OLD,
|
||||||
|
StandardPriceTypeHelper.FIELD_ZUO_SHOU,
|
||||||
|
StandardPriceTypeHelper.FIELD_JIN_KAI,
|
||||||
|
StandardPriceTypeHelper.FIELD_ZUO_JIE,
|
||||||
];
|
];
|
||||||
|
|
||||||
interface AiPickQuote {
|
interface AiPickQuote {
|
||||||
@@ -48,7 +58,8 @@ class AiPickTableRequestClient extends TableRequestClient {
|
|||||||
RequestHelper.build().base(this.frameId, this.pageId, this, this.requestParams).request();
|
RequestHelper.build().base(this.frameId, this.pageId, this, this.requestParams).request();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected afterParserModel(tableData: TableData, _structData: StuffTableStruct): void {
|
protected afterParserModel(tableData: TableData, structData: StuffTableStruct): void {
|
||||||
|
applyStandardPriceToTableData(tableData, structData, FIELD_IDS);
|
||||||
const quoteMap: Map<string, AiPickQuote> = this.toQuoteMap(tableData);
|
const quoteMap: Map<string, AiPickQuote> = this.toQuoteMap(tableData);
|
||||||
const nextCardData: CardData = this.mergeQuoteData(quoteMap);
|
const nextCardData: CardData = this.mergeQuoteData(quoteMap);
|
||||||
this.sourceCardData = nextCardData;
|
this.sourceCardData = nextCardData;
|
||||||
@@ -71,7 +82,7 @@ class AiPickTableRequestClient extends TableRequestClient {
|
|||||||
}
|
}
|
||||||
const quote: AiPickQuote = {
|
const quote: AiPickQuote = {
|
||||||
price: this.getNumber(row, TableConstants.DATA_ID_PRICE),
|
price: this.getNumber(row, TableConstants.DATA_ID_PRICE),
|
||||||
priceChg: this.getNumber(row, TableConstants.DATA_ID_ZF_YTD),
|
priceChg: this.getNumber(row, TableConstants.DATA_ID_ZF),
|
||||||
};
|
};
|
||||||
quoteMap.set(`${codeValue}_${marketValue}`, quote);
|
quoteMap.set(`${codeValue}_${marketValue}`, quote);
|
||||||
});
|
});
|
||||||
@@ -148,12 +159,15 @@ export class AiPickHqRequestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private buildRequestParams(contracts: PickContractItem[]): string {
|
private buildRequestParams(contracts: PickContractItem[]): string {
|
||||||
|
const computeMode: StandardPriceType =
|
||||||
|
QuoteCustomSettingManager.getInstance().getStandardPriceType();
|
||||||
return `\r\nsortid=-1\r\n` +
|
return `\r\nsortid=-1\r\n` +
|
||||||
`sortorder=0\r\n` +
|
`sortorder=0\r\n` +
|
||||||
`push=1\r\n` +
|
`push=1\r\n` +
|
||||||
`dataitem=${FIELD_IDS.map((fieldId: number): string => `${fieldId},`).join('')}\r\n` +
|
`dataitem=${FIELD_IDS.map((fieldId: number): string => `${fieldId},`).join('')}\r\n` +
|
||||||
`codelist=${this.formatCodeList(contracts)}\r\n` +
|
`codelist=${this.formatCodeList(contracts)}\r\n` +
|
||||||
`update=1\r\n` +
|
`update=1\r\n` +
|
||||||
|
`computemode=${computeMode}\r\n` +
|
||||||
`scenario=qht_qihuo_sort\r\n` +
|
`scenario=qht_qihuo_sort\r\n` +
|
||||||
`precision=1\r\n` +
|
`precision=1\r\n` +
|
||||||
`pushtime=2.5\r\n`;
|
`pushtime=2.5\r\n`;
|
||||||
|
|||||||
Reference in New Issue
Block a user