From 7c807fcd308ead6389e73b25a609e6d2ae1c570c Mon Sep 17 00:00:00 2001 From: clz Date: Wed, 22 Jul 2026 16:09:46 +0800 Subject: [PATCH] =?UTF-8?q?fix(market-ranking):=20=E5=AF=B9=E9=BD=90=20Vue?= =?UTF-8?q?=20=E5=8D=A1=E7=89=87=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/ets/market-ranking/MarketRanking.ets | 228 ++++++++++++------ .../ets/market-ranking/MarketRankingMock.ets | 20 ++ 2 files changed, 178 insertions(+), 70 deletions(-) diff --git a/entry/src/main/ets/market-ranking/MarketRanking.ets b/entry/src/main/ets/market-ranking/MarketRanking.ets index d735f20..e903009 100644 --- a/entry/src/main/ets/market-ranking/MarketRanking.ets +++ b/entry/src/main/ets/market-ranking/MarketRanking.ets @@ -13,6 +13,20 @@ export struct MarketRanking { @State primaryIdx: number = 0; @State secondaryIdx: number = 0; @State unfolded: boolean = false; + @State tabViewportWidth: number = 0; + @State tabContentWidth: number = 0; + @State tabScrollOffset: number = 0; + + private showTabGradient(): boolean { + const maxOffset = this.tabContentWidth - this.tabViewportWidth; + return maxOffset > 0 && this.tabScrollOffset < maxOffset; + } + + private emptyHeight(): number { + const rowHeight = 45; + const headerHeight = 24; + return (this.unfolded ? MAX_SIZE : NORMAL_SIZE) * rowHeight + headerHeight; + } // 第三列标题随 Tab 变化 private thirdColumnTitle(): string { @@ -73,40 +87,69 @@ export struct MarketRanking { .borderRadius(11) .backgroundColor($r('app.color.pill_inactive_bg')) .textAlign(TextAlign.Center) - .margin({ left: 16 }) + .margin({ left: 8 }) .onClick(() => { this.unfolded = !this.unfolded; }) } .width('100%') - .padding({ bottom: 16 }) + .height(48) + .alignItems(VerticalAlign.Center) // 一级 Tab(胶囊按钮,可横向滚动) - Scroll() { - Row({ space: 8 }) { - ForEach(TAB_METRICS, (metric: TabMetric, index: number) => { - Text(metric.label) - .fontSize(14) - .fontWeight(this.primaryIdx === index ? FontWeight.Bold : FontWeight.Normal) - .fontColor(this.primaryIdx === index ? $r('app.color.text_blue') : $r('app.color.text_secondary')) - .constraintSize({ minWidth: 63 }) - .textAlign(TextAlign.Center) - .padding({ top: 6, bottom: 6, left: 12, right: 12 }) - .borderRadius(4) - .backgroundColor(this.primaryIdx === index - ? $r('app.color.pill_active_bg') - : $r('app.color.pill_inactive_bg')) - .onClick(() => { - this.primaryIdx = index; - this.secondaryIdx = 0; - }) - }, (metric: TabMetric) => metric.id) + Stack({ alignContent: Alignment.End }) { + Scroll() { + Row({ space: 8 }) { + ForEach(TAB_METRICS, (metric: TabMetric, index: number) => { + Text(metric.label) + .fontSize(14) + .fontWeight(this.primaryIdx === index ? FontWeight.Bold : FontWeight.Normal) + .fontColor(this.primaryIdx === index + ? $r('app.color.text_blue') + : $r('app.color.text_secondary')) + .constraintSize({ minWidth: 63 }) + .textAlign(TextAlign.Center) + .padding({ top: 6, bottom: 6, left: 12, right: 12 }) + .borderRadius(4) + .backgroundColor(this.primaryIdx === index + ? $r('app.color.pill_active_bg') + : $r('app.color.pill_inactive_bg')) + .onClick(() => { + this.primaryIdx = index; + this.secondaryIdx = 0; + }) + }, (metric: TabMetric) => metric.id) + } + .onAreaChange((oldValue: Area, newValue: Area) => { + this.tabContentWidth = Number(newValue.width); + }) + } + .width('100%') + .height(30) + .padding({ right: 10 }) + .scrollable(ScrollDirection.Horizontal) + .scrollBar(BarState.Off) + .align(Alignment.Start) + .onScroll((xOffset: number, _yOffset: number) => { + this.tabScrollOffset = xOffset; + }) + + if (this.showTabGradient()) { + Row() + .width(24) + .height(30) + .linearGradient({ + angle: 90, + colors: [['#00FFFFFF', 0], [$r('app.color.card_bg'), 1]], + }) + .hitTestBehavior(HitTestMode.None) } } .width('100%') - .scrollable(ScrollDirection.Horizontal) - .scrollBar(BarState.Off) - .align(Alignment.Start) + .height(30) + .onAreaChange((oldValue: Area, newValue: Area) => { + this.tabViewportWidth = Number(newValue.width); + }) // 二级 Tab(仅涨速/跌速出现,右对齐文字 + 分隔线) if (TAB_METRICS[this.primaryIdx].hasChildren) { @@ -133,55 +176,100 @@ export struct MarketRanking { } .width('100%') .justifyContent(FlexAlign.End) - .margin({ top: 8 }) + .padding({ left: 10, right: 10 }) + .margin({ top: 8, left: -10, right: -10 }) } - // 表头 - Row() { - Text('合约名称').fontSize(12).fontColor($r('app.color.text_tertiary')).width('35%') - Text('最新价').fontSize(12).fontColor($r('app.color.text_tertiary')).layoutWeight(1).textAlign(TextAlign.End) - Text(this.thirdColumnTitle()) - .fontSize(12) - .fontColor($r('app.color.text_tertiary')) - .layoutWeight(1) - .textAlign(TextAlign.End) - } - .width('100%') - .margin({ top: 10 }) - .padding({ bottom: 2 }) - .border({ width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) + if (this.vm.currentList(this.primaryIdx, this.secondaryIdx).length === 0) { + Column() { + Text('暂无数据') + .fontSize(14) + .fontColor($r('app.color.text_grey')) + } + .width('100%') + .height(this.emptyHeight()) + .margin({ top: 10 }) + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + } else { + // 表头 + Row() { + Text('合约名称') + .fontSize(12) + .lineHeight(21) + .fontColor($r('app.color.text_tertiary')) + .width('35%') + Text('最新价') + .fontSize(12) + .lineHeight(21) + .fontColor($r('app.color.text_tertiary')) + .layoutWeight(1) + .margin({ left: 8 }) + .textAlign(TextAlign.End) + Text(this.thirdColumnTitle()) + .fontSize(12) + .lineHeight(21) + .fontColor($r('app.color.text_tertiary')) + .layoutWeight(1) + .margin({ left: 8 }) + .textAlign(TextAlign.End) + } + .width('100%') + .height(23) + .margin({ top: 10 }) + .padding({ bottom: 2 }) + .alignItems(VerticalAlign.Center) + .border({ width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) - // 表格列表 - ForEach( - this.vm.currentList(this.primaryIdx, this.secondaryIdx).slice(0, this.unfolded ? MAX_SIZE : NORMAL_SIZE), - (item: RankItem, index: number) => { - Row() { - Text(item.name).fontSize(16).fontColor($r('app.color.text_primary')).width('35%') - Text(`${item.price}`) - .fontSize(16) - .fontColor(riseFallColor(item.price_chg)) - .layoutWeight(1) - .textAlign(TextAlign.End) - Text(this.thirdColumnValue(item)) - .fontSize(16) - .fontColor(this.thirdColumnColor(item)) - .layoutWeight(1) - .textAlign(TextAlign.End) - } - .width('100%') - .padding({ top: 12, bottom: 12 }) - .border(index === Math.min( - this.unfolded ? MAX_SIZE : NORMAL_SIZE, - this.vm.currentList(this.primaryIdx, this.secondaryIdx).length, - ) - 1 - ? undefined - : { width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) - .onClick(() => { - this.vm.jumpToDetail(item); - }) - }, - (item: RankItem) => item.code, - ) + // 表格列表 + ForEach( + this.vm.currentList(this.primaryIdx, this.secondaryIdx).slice(0, this.unfolded ? MAX_SIZE : NORMAL_SIZE), + (item: RankItem, index: number) => { + Row() { + Text(item.name) + .fontSize(16) + .lineHeight(21) + .fontColor($r('app.color.text_primary')) + .width('35%') + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + Text(`${item.price}`) + .fontSize(16) + .lineHeight(21) + .fontFamily('monospace') + .fontColor(riseFallColor(item.price_chg)) + .layoutWeight(1) + .margin({ left: 8 }) + .textAlign(TextAlign.End) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + Text(this.thirdColumnValue(item)) + .fontSize(16) + .lineHeight(21) + .fontFamily('monospace') + .fontColor(this.thirdColumnColor(item)) + .layoutWeight(1) + .margin({ left: 8 }) + .textAlign(TextAlign.End) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + } + .width('100%') + .height(45) + .alignItems(VerticalAlign.Center) + .border(index === Math.min( + this.unfolded ? MAX_SIZE : NORMAL_SIZE, + this.vm.currentList(this.primaryIdx, this.secondaryIdx).length, + ) - 1 + ? undefined + : { width: { bottom: 0.5 }, color: $r('app.color.divider_color') }) + .onClick(() => { + this.vm.jumpToDetail(item); + }) + }, + (item: RankItem) => item.code, + ) + } } .width('100%') } diff --git a/entry/src/main/ets/market-ranking/MarketRankingMock.ets b/entry/src/main/ets/market-ranking/MarketRankingMock.ets index 76ce026..48997b9 100644 --- a/entry/src/main/ets/market-ranking/MarketRankingMock.ets +++ b/entry/src/main/ets/market-ranking/MarketRankingMock.ets @@ -26,12 +26,16 @@ export const MOCK_RANK_LISTS: RankItem[][] = [ { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, turnover: 1286000 }, { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, turnover: 963000 }, { code: 'I2505', market: '70', name: '铁矿石2505', price: 812, price_chg: -2.86, turnover: 841000 }, + { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, turnover: 765000 }, + { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, turnover: 628000 }, ], // increPosit 日增仓(原始数值,未换算单位) [ { code: 'CU2501', market: '70', name: '沪铜2501', price: 68520, price_chg: 3.21, incre_posit: 12000 }, { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, incre_posit: 9000 }, { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, incre_posit: -6000 }, + { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, incre_posit: 5200 }, + { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, incre_posit: 3800 }, ], ]; @@ -45,24 +49,32 @@ export const MOCK_SPEED_LISTS: RankItem[][][] = [ { code: 'CU2501', market: '70', name: '沪铜2501', price: 68520, price_chg: 3.21, chg_speed: 0.85 }, { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, chg_speed: 0.62 }, { code: 'SR2505', market: '70', name: '白糖2505', price: 6234, price_chg: 1.1, chg_speed: 0.41 }, + { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, chg_speed: 0.36 }, + { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, chg_speed: 0.29 }, ], // 5分钟 [ { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, chg_speed: 1.34 }, { code: 'CU2501', market: '70', name: '沪铜2501', price: 68520, price_chg: 3.21, chg_speed: 1.02 }, { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, chg_speed: 0.78 }, + { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, chg_speed: 0.63 }, + { code: 'SR2505', market: '70', name: '白糖2505', price: 6234, price_chg: 1.1, chg_speed: 0.51 }, ], // 10分钟 [ { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, chg_speed: 2.15 }, { code: 'SR2505', market: '70', name: '白糖2505', price: 6234, price_chg: 1.1, chg_speed: 1.76 }, { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, chg_speed: 1.3 }, + { code: 'CU2501', market: '70', name: '沪铜2501', price: 68520, price_chg: 3.21, chg_speed: 1.16 }, + { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, chg_speed: 0.92 }, ], // 15分钟 [ { code: 'RB2505', market: '70', name: '螺纹钢2505', price: 3452, price_chg: 2.15, chg_speed: 2.68 }, { code: 'CU2501', market: '70', name: '沪铜2501', price: 68520, price_chg: 3.21, chg_speed: 2.21 }, { code: 'AU2506', market: '70', name: '沪金2506', price: 598.4, price_chg: 1.52, chg_speed: 1.85 }, + { code: 'M2505', market: '70', name: '豆粕2505', price: 2986, price_chg: 1.87, chg_speed: 1.61 }, + { code: 'SR2505', market: '70', name: '白糖2505', price: 6234, price_chg: 1.1, chg_speed: 1.42 }, ], ], // fallSpeed 跌速 @@ -72,24 +84,32 @@ export const MOCK_SPEED_LISTS: RankItem[][][] = [ { code: 'I2505', market: '70', name: '铁矿石2505', price: 812, price_chg: -2.86, chg_speed: -0.73 }, { code: 'FG2505', market: '70', name: '玻璃2505', price: 1289, price_chg: -1.34, chg_speed: -0.55 }, { code: 'SM2505', market: '70', name: '锰硅2505', price: 5876, price_chg: -0.92, chg_speed: -0.38 }, + { code: 'JD2505', market: '70', name: '鸡蛋2505', price: 3568, price_chg: -1.75, chg_speed: -0.31 }, + { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, chg_speed: -0.25 }, ], // 5分钟 [ { code: 'FG2505', market: '70', name: '玻璃2505', price: 1289, price_chg: -1.34, chg_speed: -1.12 }, { code: 'SM2505', market: '70', name: '锰硅2505', price: 5876, price_chg: -0.92, chg_speed: -0.89 }, { code: 'I2505', market: '70', name: '铁矿石2505', price: 812, price_chg: -2.86, chg_speed: -0.64 }, + { code: 'JD2505', market: '70', name: '鸡蛋2505', price: 3568, price_chg: -1.75, chg_speed: -0.52 }, + { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, chg_speed: -0.43 }, ], // 10分钟 [ { code: 'SM2505', market: '70', name: '锰硅2505', price: 5876, price_chg: -0.92, chg_speed: -1.87 }, { code: 'JD2505', market: '70', name: '鸡蛋2505', price: 3568, price_chg: -1.75, chg_speed: -1.45 }, { code: 'FG2505', market: '70', name: '玻璃2505', price: 1289, price_chg: -1.34, chg_speed: -1.06 }, + { code: 'I2505', market: '70', name: '铁矿石2505', price: 812, price_chg: -2.86, chg_speed: -0.91 }, + { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, chg_speed: -0.76 }, ], // 15分钟 [ { code: 'JD2505', market: '70', name: '鸡蛋2505', price: 3568, price_chg: -1.75, chg_speed: -2.34 }, { code: 'I2505', market: '70', name: '铁矿石2505', price: 812, price_chg: -2.86, chg_speed: -1.98 }, { code: 'SM2505', market: '70', name: '锰硅2505', price: 5876, price_chg: -0.92, chg_speed: -1.52 }, + { code: 'FG2505', market: '70', name: '玻璃2505', price: 1289, price_chg: -1.34, chg_speed: -1.31 }, + { code: 'P2505', market: '70', name: '棕榈油2505', price: 7654, price_chg: -2.13, chg_speed: -1.17 }, ], ], ];