fix(market-ranking): 对齐 Vue 卡片布局
This commit is contained in:
@@ -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%')
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user