diff --git a/entry/src/main/ets/ai-pick/AiPickNodeComponent.ets b/entry/src/main/ets/ai-pick/AiPickNodeComponent.ets index cf0c1fe..16bcee7 100644 --- a/entry/src/main/ets/ai-pick/AiPickNodeComponent.ets +++ b/entry/src/main/ets/ai-pick/AiPickNodeComponent.ets @@ -19,6 +19,7 @@ import { EMPTY_IMAGE_LIGHT, INFO_IMAGE_DARK, INFO_IMAGE_LIGHT, + MAX_ITEMS, RIGHT_ARROW_DARK, RIGHT_ARROW_LIGHT, TITLE_ARROW_DARK, @@ -29,6 +30,18 @@ interface StrategyDescParams { tabIdx: number; } +const CARD_TITLE_HEIGHT = 48; +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 CARD_CONTENT_HEIGHT = CARD_TITLE_HEIGHT + MAIN_CONTENT_HEIGHT; +const NO_CONTRACT_HEIGHT = STRATEGY_DESC_HEIGHT + TABLE_HEIGHT; + @Component export struct AiPickNodeComponent { // 当前卡片配置。 @@ -142,31 +155,32 @@ export struct AiPickNodeComponent { @Builder CardTitle() { - Row({ space: 4 }) { + Row() { Text(this.cardConfig?.card_title.value || $r('app.string.ai_pick_title')) .fontSize(18) - .fontWeight(FontWeight.Bold) + .fontWeight(500) .fontColor($r('app.color.text_primary')) .maxLines(1) if ((this.cardConfig?.card_url.android ?? '') !== '' || (this.cardConfig?.card_url.ios ?? '') !== '') { Image(this.isDarkMode ? TITLE_ARROW_DARK : TITLE_ARROW_LIGHT) - .width(12) - .height(12) + .width(20) + .height(20) } if ((this.cardConfig?.explain_message ?? '') !== '') { Image(this.isDarkMode ? INFO_IMAGE_DARK : INFO_IMAGE_LIGHT) .width(16) .height(16) + .margin({ left: 8 }) .onClick((event: ClickEvent) => { this.showExplainSheet = true; }) } } .width('100%') - .height(48) + .height(CARD_TITLE_HEIGHT) .alignItems(VerticalAlign.Center) .onClick(() => { this.jumpToCardTitle(); @@ -232,16 +246,18 @@ export struct AiPickNodeComponent { if (this.cardData.tabs[$$.tabIdx].strategy.tagList.length > 0) { Row({ space: 4 }) { ForEach(this.cardData.tabs[$$.tabIdx].strategy.tagList, (tag: string) => { - Text(tag) - .fontSize(11) - .lineHeight(18) - .fontColor($r('app.color.text_blue')) - .maxLines(1) - .textOverflow({ overflow: TextOverflow.Ellipsis }) + Row() { + Text(tag) + .fontSize(11) + .fontColor($r('app.color.text_blue')) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + } .height(18) .padding({ left: 3, right: 3 }) .borderRadius(2) .border({ width: 0.5, color: $r('app.color.text_blue') }) + .alignItems(VerticalAlign.Center) .onClick(() => { this.jumpToLabel( this.cardData.tabs[$$.tabIdx].strategy, @@ -255,7 +271,6 @@ export struct AiPickNodeComponent { } .layoutWeight(1) .alignItems(HorizontalAlign.Start) - .margin({ bottom: 10 }) // 右侧:策略图片(仅系统策略有图,右侧 image) // imgs 长度>0 且当前选中位(imgs[0],暂无主题切换)非空才渲染 @@ -268,7 +283,8 @@ export struct AiPickNodeComponent { } } .width('100%') - .margin({ top: 10 }) + .height(STRATEGY_DESC_HEIGHT) + .padding({ top: 10, bottom: 10 }) .alignItems(VerticalAlign.Top) .onClick(() => { this.jumpToStrategyDetail( @@ -285,11 +301,11 @@ export struct AiPickNodeComponent { Column() { Text($r('app.string.ai_pick_loading')) - .fontSize(16) + .fontSize(14) .fontColor($r('app.color.text_grey')) } .width('100%') - .height(240) + .height(MAIN_CONTENT_HEIGHT) .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } else { @@ -297,6 +313,9 @@ export struct AiPickNodeComponent { } } .width('100%') + .backgroundColor($r('app.color.card_bg')) + .borderRadius(4) + .padding({ left: 10, right: 10, bottom: 10 }) .bindSheet(this.showExplainSheet, this.ExplainSheet, { height: SheetSize.FIT_CONTENT, dragBar: true, @@ -325,14 +344,15 @@ export struct AiPickNodeComponent { ForEach(this.cardData.tabs, (tab: PickTabData, index: number) => { Text(`${tab.strategy.name}(${tab.strategy.count})`) .fontSize(14) - .fontWeight(this.tabIdx === index ? FontWeight.Bold : FontWeight.Normal) + .fontWeight(this.tabIdx === index ? FontWeight.Medium : FontWeight.Normal) .fontColor(this.tabIdx === index ? $r('app.color.text_blue') : $r('app.color.text_secondary')) - .constraintSize({ minWidth: 63 }) + .constraintSize({ minWidth: 66 }) .maxLines(1) .textAlign(TextAlign.Center) - .padding({ top: 6, bottom: 6, left: 12, right: 12 }) + .height(TAB_BAR_HEIGHT) + .padding({ left: 8, right: 8 }) .borderRadius(4) .backgroundColor(this.tabIdx === index ? $r('app.color.pill_active_bg') @@ -347,7 +367,8 @@ export struct AiPickNodeComponent { }) } .width('100%') - .height(30) + .height(TAB_BAR_HEIGHT) + .padding({ right: 10 }) .scrollable(ScrollDirection.Horizontal) .scrollBar(BarState.Off) .align(Alignment.Start) @@ -358,16 +379,17 @@ export struct AiPickNodeComponent { if (this.showTabGradient()) { Row() .width(24) - .height(30) + .height(TAB_BAR_HEIGHT) .linearGradient({ angle: 90, - colors: [['#00FFFFFF', 0], [$r('app.color.card_bg'), 1]], + colors: [[$r('app.color.tab_gradient_start'), 0], + [$r('app.color.card_bg'), 1]], }) .hitTestBehavior(HitTestMode.None) } } .width('100%') - .height(30) + .height(TAB_BAR_HEIGHT) .onAreaChange((oldValue: Area, newValue: Area) => { this.tabViewportWidth = Number(newValue.width); }) @@ -380,97 +402,102 @@ export struct AiPickNodeComponent { if (this.cardData.tabs[this.tabIdx].items.length === 0) { this.EmptyState($r('app.string.ai_pick_no_contract')) } else { - // ── 表头 ────────────────────────────────────────────── - Row() { - Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[0])) - .fontSize(12) - .fontColor($r('app.color.text_tertiary')) - .width('35%') - Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[1])) - .fontSize(12) - .fontColor($r('app.color.text_tertiary')) - .layoutWeight(1) - .margin({ left: 8 }) - .textAlign(TextAlign.End) - Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[2])) - .fontSize(12) - .fontColor($r('app.color.text_tertiary')) - .layoutWeight(1) - .margin({ left: 8 }) - .textAlign(TextAlign.End) - } - .width('100%') - .height(24) - .margin({ top: 8 }) - .padding({ bottom: 2 }) - .alignItems(VerticalAlign.Center) - .border({ width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) + Column() { + // ── 表头 ──────────────────────────────────────────── + Row({ space: 8 }) { + Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[0])) + .fontSize(14) + .fontColor($r('app.color.text_tertiary')) + .width('35%') + Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[1])) + .fontSize(14) + .fontColor($r('app.color.text_tertiary')) + .layoutWeight(1) + .textAlign(TextAlign.End) + Text(formatColName(this.cardData.tabs[this.tabIdx].keysList[2])) + .fontSize(14) + .fontColor($r('app.color.text_tertiary')) + .layoutWeight(1) + .textAlign(TextAlign.End) + } + .width('100%') + .height(TABLE_HEADER_HEIGHT) - // ── 合约列表 ────────────────────────────────────────── - ForEach( - this.cardData.tabs[this.tabIdx].items, - (item: PickContractItem) => { - Row() { - Row({ space: 5 }) { - Text(item.name) + // ── 合约列表 ──────────────────────────────────────── + ForEach( + this.cardData.tabs[this.tabIdx].items, + (item: PickContractItem) => { + Row({ space: 8 }) { + Row({ space: 5 }) { + Text(item.name) + .fontSize(16) + .maxFontSize(16) + .minFontSize(9) + .fontColor($r('app.color.text_primary')) + .layoutWeight(1) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + if (item.isMain) { + Text($r('app.string.ai_pick_main_contract')) + .fontSize(11) + .fontColor($r('app.color.color_orange')) + .width(16) + .height(16) + .textAlign(TextAlign.Center) + .borderRadius(2) + .backgroundColor($r('app.color.bg_orange')) + } + } + .width('35%') + .alignItems(VerticalAlign.Center) + + Text(cellValue( + this.cardData.tabs[this.tabIdx].keysList[1], + item, + this.cardData.tabs[this.tabIdx].fieldList, + )) .fontSize(16) - .fontColor($r('app.color.text_primary')) + .maxFontSize(16) + .minFontSize(9) + .fontWeight(500) + .fontFamily('monospace') + .fontColor(cellColor(this.cardData.tabs[this.tabIdx].keysList[1], item)) + .layoutWeight(1) + .textAlign(TextAlign.End) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + + Text(cellValue( + this.cardData.tabs[this.tabIdx].keysList[2], + item, + this.cardData.tabs[this.tabIdx].fieldList, + )) + .fontSize(16) + .maxFontSize(16) + .minFontSize(9) + .fontWeight(500) + .fontFamily('monospace') + .fontColor(cellColor(this.cardData.tabs[this.tabIdx].keysList[2], item)) + .layoutWeight(1) + .textAlign(TextAlign.End) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) - if (item.isMain) { - Text($r('app.string.ai_pick_main_contract')) - .fontSize(11) - .fontColor($r('app.color.color_orange')) - .width(16) - .height(16) - .textAlign(TextAlign.Center) - .borderRadius(2) - .backgroundColor($r('app.color.bg_orange')) - } } - .width('35%') + .width('100%') + .height(TABLE_ROW_HEIGHT) .alignItems(VerticalAlign.Center) - - Text(cellValue( - this.cardData.tabs[this.tabIdx].keysList[1], - item, - this.cardData.tabs[this.tabIdx].fieldList, - )) - .fontSize(16) - .fontFamily('monospace') - .fontColor(cellColor(this.cardData.tabs[this.tabIdx].keysList[1], item)) - .layoutWeight(1) - .margin({ left: 8 }) - .textAlign(TextAlign.End) - .maxLines(1) - .textOverflow({ overflow: TextOverflow.Ellipsis }) - - Text(cellValue( - this.cardData.tabs[this.tabIdx].keysList[2], - item, - this.cardData.tabs[this.tabIdx].fieldList, - )) - .fontSize(16) - .fontFamily('monospace') - .fontColor(cellColor(this.cardData.tabs[this.tabIdx].keysList[2], item)) - .layoutWeight(1) - .margin({ left: 8 }) - .textAlign(TextAlign.End) - .maxLines(1) - .textOverflow({ overflow: TextOverflow.Ellipsis }) - } - .width('100%') - .height(44) - .alignItems(VerticalAlign.Center) - .border({ width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) - .onClick(() => { - this.jumpToDetail(item); - }) - }, - // 行情字段参与 key,确保 price/priceChg 变化后对应列表行重新渲染。 - (item: PickContractItem) => - `${item.contract}_${item.market}_${item.price ?? ''}_${item.priceChg ?? ''}`, - ) + .border({ width: { top: 1 }, color: $r('app.color.divider_color') }) + .onClick(() => { + this.jumpToDetail(item); + }) + }, + // 行情字段参与 key,确保整体替换 CardData 后列表行同步刷新。 + (item: PickContractItem) => + `${item.contract}_${item.market}_${item.price ?? ''}_${item.priceChg ?? ''}`, + ) + } + .width('100%') + .height(TABLE_HEIGHT) } // ── 一句话定制策略 ────────────────────────────────────── @@ -484,30 +511,30 @@ export struct AiPickNodeComponent { .height(14) .margin({ top: 2 }) } - .width('100%') - .justifyContent(FlexAlign.Center) - .alignItems(VerticalAlign.Center) - .margin({ top: 6 }) - .onClick(() => { - this.jumpToNewHome(); - }) + .width('100%') + .height(CUSTOM_STRATEGY_HEIGHT) + .justifyContent(FlexAlign.Center) + .alignItems(VerticalAlign.Center) + .onClick(() => { + this.jumpToNewHome(); + }) } .width('100%') + .height(CARD_CONTENT_HEIGHT) } @Builder EmptyState(message: ResourceStr) { Column() { Image(this.isDarkMode ? EMPTY_IMAGE_DARK : EMPTY_IMAGE_LIGHT) - .width(120) - .height(120) - .margin({ bottom: 8 }) + .width(100) + .height(100) Text(message) - .fontSize(16) + .fontSize(14) .fontColor($r('app.color.text_grey')) } .width('100%') - .height(240) + .height(NO_CONTRACT_HEIGHT) .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 091797f..f315972 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -1,19 +1,37 @@ -import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { AbilityConstant, Configuration, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { resourceManager } from '@kit.LocalizationKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; const DOMAIN = 0x0000; export default class EntryAbility extends UIAbility { + private updateDarkMode(isDarkMode: boolean): void { + AppStorage.setOrCreate('enableDarkMode', isDarkMode); + } + + private syncDarkModeFromResources(): void { + const configuration: resourceManager.Configuration = + this.context.resourceManager.getConfigurationSync(); + this.updateDarkMode(configuration.colorMode === resourceManager.ColorMode.DARK); + } + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { try { this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); } catch (err) { hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); } + this.syncDarkModeFromResources(); hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); } + onConfigurationUpdate(newConfig: Configuration): void { + if (newConfig.colorMode !== undefined) { + this.updateDarkMode(newConfig.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK); + } + } + onDestroy(): void { hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); } @@ -37,7 +55,7 @@ export default class EntryAbility extends UIAbility { } onForeground(): void { - // Ability has brought to foreground + this.syncDarkModeFromResources(); hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); } @@ -45,4 +63,4 @@ export default class EntryAbility extends UIAbility { // Ability has back to background hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); } -} \ No newline at end of file +} diff --git a/entry/src/main/ets/market-ranking/MarketRankingNodeComponent.ets b/entry/src/main/ets/market-ranking/MarketRankingNodeComponent.ets index 859b40d..b1716d3 100644 --- a/entry/src/main/ets/market-ranking/MarketRankingNodeComponent.ets +++ b/entry/src/main/ets/market-ranking/MarketRankingNodeComponent.ets @@ -258,7 +258,7 @@ export struct MarketRankingNodeComponent { .height(30) .linearGradient({ angle: 90, - colors: [[$r('app.color.transparent_white'), 0], [$r('app.color.card_bg'), 1]], + colors: [[$r('app.color.tab_gradient_start'), 0], [$r('app.color.card_bg'), 1]], }) .hitTestBehavior(HitTestMode.None) } diff --git a/entry/src/main/resources/base/element/color.json b/entry/src/main/resources/base/element/color.json index 436f278..0ef6bc6 100644 --- a/entry/src/main/resources/base/element/color.json +++ b/entry/src/main/resources/base/element/color.json @@ -16,6 +16,7 @@ { "name": "color_fall", "value": "#07AB4B" }, { "name": "color_orange", "value": "#FF661A" }, { "name": "bg_orange", "value": "#1AFF661A" }, - { "name": "transparent_white", "value": "#00FFFFFF" } + { "name": "transparent_white", "value": "#00FFFFFF" }, + { "name": "tab_gradient_start", "value": "#00FFFFFF" } ] } diff --git a/entry/src/main/resources/dark/element/color.json b/entry/src/main/resources/dark/element/color.json index 2f5b3ae..83fec35 100644 --- a/entry/src/main/resources/dark/element/color.json +++ b/entry/src/main/resources/dark/element/color.json @@ -13,6 +13,7 @@ { "name": "pill_active_bg", "value": "#1A527DFF" }, { "name": "pill_inactive_bg", "value": "#0FFFFFFF" }, { "name": "color_rise", "value": "#FF2436" }, - { "name": "color_fall", "value": "#07AB4B" } + { "name": "color_fall", "value": "#07AB4B" }, + { "name": "tab_gradient_start", "value": "#002B2B2B" } ] }