Initial commit: @b2c/first_page HarmonyOS stage-mode HAR
## Repository - HarmonyOS stage-mode HAR module, consumed by host app - No standalone build — hvigorw, oh_modules, and ../biz_quote absent here ## Architecture ### Feed Cards - FirstPage.createNodeView dispatches cards by FirstPageConstant.KEY_* - Card config from first_page_cards_config.json loaded by FirstPageCardsConfigLoader - Public entrypoint: Index.ets ### Market Ranking (src/main/ets/market-ranking/) - HTTP: MarketRankingDataFetcher fetches recommend_futures contracts - HQ: MarketRankingHqRequestClient subscribes via 4106/frame 2201/scenario qht_qihuo_sort - TCP reconnect rebuilds subscription from original HTTP contract list - Async callbacks guarded by request/subscription versions ### Other Cards - HotList, CommodityOptions, AiDiagnosis, AiRiseFall, SelfSelectedStock, CustomEntryList, FourEntryList - Each has DataFetcher + HQ request client + NodeComponent ## Key Changes (from CardHarmonyOS reference) - Added MetricId, PeriodId, SortOrder enums (MarketRankingModels.ets) - Replaced string comparisons with enum switches in thirdColumnTitle/Value/Color - Removed redundant undefined guards in thirdColumnColor/priceColor, delegated to riseFallColor - Inlined priceColor(), use riseFallColor directly - Tab bar Stack.height(30), Alignment.End (reverted from 46/TopEnd) - Name column fontWeight removed (default regular)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { AppInfoConfig, GlobalContext } from 'biz_common'
|
||||
import { TITLE_BAR_HEIGHT } from '../util/FirstPageConstant'
|
||||
|
||||
@Component
|
||||
export struct FirstPageContentBg {
|
||||
|
||||
@State topHeight: number = 0
|
||||
@State topContentBg: Resource = $r('app.media.firstpage_top_default_bg')
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.topHeight = px2vp(GlobalContext.statusBarHeight) + TITLE_BAR_HEIGHT + (AppInfoConfig.Official?0:150);
|
||||
}
|
||||
|
||||
build() {
|
||||
Image(this.topContentBg)
|
||||
.width('100%')
|
||||
.height(this.topHeight)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
import { EmitterConstants, PreferenceService, RecommendContract, RecommendContractManager } from 'biz_common'
|
||||
import { HXUserService } from 'biz_hxservice'
|
||||
import { getSelfStock, GroupInfo, loadCustomGroups, queryWatchlistGroup, Securities } from 'service_watchlist'
|
||||
import { emitter } from '@kit.BasicServicesKit'
|
||||
import { SelectedIdOfWatchlistGroup } from 'biz_selfcode'
|
||||
import { HXUtils } from '@b2c/lib_baseui'
|
||||
|
||||
//自选股分组切换
|
||||
@Component
|
||||
export struct FirstPageSelfCodeGroupView {
|
||||
static readonly GROUPID_DEFAULT = "0_34"
|
||||
static readonly GROUPID_RECOMMEND_CONTRACT = "RECOMMEND_CONTRACT"
|
||||
static readonly SP_FILE_NAME_FIRST_PAGE_SELF_CODE_FILE_NAME = "sp_file_name_first_page_self_code"
|
||||
static readonly SP_KEY_FIRST_PAGE_SELF_CODE_LAST_GROUPID = "sp_key_first_page_self_code_last_groupid"
|
||||
@Link @Watch('onPageStatusChange') onForeground: boolean
|
||||
@State groups: GroupInfo[] = []
|
||||
@State @Watch('onGroupIndexChange') currentIndex: number = 0
|
||||
@State showPopup: boolean = false
|
||||
@Prop @Watch('onInitIndexChange') initIndex: number = 0
|
||||
onSelectGroup?: (index: number) => void
|
||||
onSelectGroupInfo?: (index: number, groupInfo: GroupInfo) => void
|
||||
private readonly OVERLAY_WIDTH = 30
|
||||
private maxGroupCount = 3
|
||||
private scroller = new Scroller()
|
||||
private lastGroupId: string | null = null
|
||||
private itemWidthArray: number[] = []
|
||||
private totalWidth: number = 0
|
||||
|
||||
aboutToAppear(): void {
|
||||
const initCurrentIndex = this.currentIndex;
|
||||
this.lastGroupId =
|
||||
PreferenceService.getStringValueSync(FirstPageSelfCodeGroupView.SP_FILE_NAME_FIRST_PAGE_SELF_CODE_FILE_NAME,
|
||||
FirstPageSelfCodeGroupView.SP_KEY_FIRST_PAGE_SELF_CODE_LAST_GROUPID, "")
|
||||
this.subscribeAllEvent()
|
||||
this.initGroupInfo()
|
||||
if (this.groups.length === 0 && !this.isTemporaryUser()) {
|
||||
queryWatchlistGroup()
|
||||
}
|
||||
this.findAndInitInitIndex()
|
||||
if (this.initIndex > 0 && this.groups.length > this.initIndex) {
|
||||
this.selectIndex(this.initIndex)
|
||||
}
|
||||
if (initCurrentIndex == this.currentIndex) {
|
||||
//说明第一次初始化,调用一次变化
|
||||
this.onGroupIndexChange()
|
||||
}
|
||||
}
|
||||
|
||||
findAndInitInitIndex() {
|
||||
if (this.lastGroupId && this.lastGroupId.length > 0) {
|
||||
this.groups.forEach((groupInfo, index) => {
|
||||
if (groupInfo.id === this.lastGroupId) {
|
||||
this.initIndex = index
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
subscribeGroupStocksChang() {
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.SELF_STOCK_GROUP_FILTER_CHANGE
|
||||
}, this.refreshAction)
|
||||
}
|
||||
|
||||
userNameChanged() {
|
||||
//
|
||||
}
|
||||
|
||||
subscribeSelfCodeQuerySucceededEvent() {
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.SELFCODE_UGC_QUERY_SUCCEEDED
|
||||
}, this.refreshAction);
|
||||
}
|
||||
|
||||
subscribeGroupQuerySucceeded() {
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.SELFGROUP_UPDATE_QUERY_SUCCEEDED
|
||||
}, this.refreshAction)
|
||||
}
|
||||
|
||||
subscribeAllEvent() {
|
||||
this.subscribeSelfCodeQuerySucceededEvent()
|
||||
this.subscribeLoginEvent()
|
||||
this.subscribeGroupQuerySucceeded()
|
||||
this.subscribeGroupStocksChang()
|
||||
}
|
||||
|
||||
unSubscribe() {
|
||||
emitter.off(EmitterConstants.SELFCODE_UGC_QUERY_SUCCEEDED, this.refreshAction)
|
||||
emitter.off(EmitterConstants.SELFGROUP_UPDATE_QUERY_SUCCEEDED, this.refreshAction)
|
||||
emitter.off(EmitterConstants.SELF_STOCK_GROUP_FILTER_CHANGE, this.refreshAction)
|
||||
|
||||
this.unSubscribeLoginEvent()
|
||||
}
|
||||
|
||||
unSubscribeGroupQuerySucceeded() {
|
||||
emitter.off(EmitterConstants.SELFGROUP_UPDATE_QUERY_SUCCEEDED, this.refreshAction)
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
this.unSubscribe()
|
||||
}
|
||||
|
||||
build() {
|
||||
if (this.groups.length > 0) {
|
||||
Row() {
|
||||
Row() {
|
||||
Scroll(this.scroller) {
|
||||
Row() {
|
||||
ForEach(this.groups, (item: GroupInfo, index: number) => {
|
||||
this.buildItem(item, index)
|
||||
})
|
||||
}
|
||||
}
|
||||
.scrollBar(BarState.Off)
|
||||
.scrollable(ScrollDirection.Horizontal)
|
||||
.width('auto')
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
}
|
||||
.width('100%')
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.visibility(this.groups.length > 1 ? Visibility.Visible : Visibility.None)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildItem(item: GroupInfo, index: number) {
|
||||
Column() {
|
||||
Text(item.name)
|
||||
.fontSize(15)
|
||||
.fontColor(index === this.currentIndex ? $r('app.color.elements_text_primary_01') : $r('app.color.elements_text_primary_02'))
|
||||
.backgroundColor(index === this.currentIndex ? $r('app.color.color_2e58ff_alp_10') :
|
||||
$r('app.color.surface_layer3_background'))
|
||||
.borderColor($r('app.color.elements_text_primary_01'))
|
||||
.borderRadius(2)
|
||||
.padding({
|
||||
left: 10,
|
||||
top: 5,
|
||||
bottom: 5,
|
||||
right: 10
|
||||
})
|
||||
|
||||
}
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.height(35)
|
||||
.padding({ left: index == 0 ? 0 : 5, right: 5 })
|
||||
.onClick(() => {
|
||||
if (this.currentIndex != index) {
|
||||
this.selectIndex(index)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private refreshAction = () => {
|
||||
this.initGroupInfo()
|
||||
}
|
||||
|
||||
private subscribeLoginEvent() {
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.USER_LOGIN
|
||||
}, this.refreshAction)
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.USER_LOGOUT
|
||||
}, this.refreshAction);
|
||||
}
|
||||
|
||||
private unSubscribeLoginEvent() {
|
||||
emitter.off(EmitterConstants.USER_LOGIN, this.refreshAction);
|
||||
emitter.off(EmitterConstants.USER_LOGOUT, this.refreshAction);
|
||||
}
|
||||
|
||||
private onGroupChange = () => {
|
||||
this.initGroupInfo()
|
||||
}
|
||||
private onUserLogin = () => {
|
||||
if (this.isTemporaryUser()) {
|
||||
SelectedIdOfWatchlistGroup.setDefaultId()
|
||||
}
|
||||
this.initGroupInfo()
|
||||
}
|
||||
|
||||
private onPageStatusChange() {
|
||||
if (this.onForeground) {
|
||||
this.initGroupInfo()
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.SELF_STOCK_GROUP_FILTER_CHANGE
|
||||
}, this.onGroupChange)
|
||||
|
||||
emitter.on({
|
||||
eventId: EmitterConstants.USER_LOGIN
|
||||
}, this.onUserLogin)
|
||||
} else {
|
||||
emitter.off(EmitterConstants.SELF_STOCK_GROUP_FILTER_CHANGE, this.onGroupChange)
|
||||
emitter.off(EmitterConstants.USER_LOGIN, this.onUserLogin)
|
||||
}
|
||||
}
|
||||
|
||||
private onGroupIndexChange() {
|
||||
if (this.onSelectGroup) {
|
||||
this.onSelectGroup(this.currentIndex)
|
||||
}
|
||||
if (this.onSelectGroupInfo && this.currentIndex < this.groups.length) {
|
||||
this.onSelectGroupInfo(this.currentIndex, this.groups[this.currentIndex])
|
||||
}
|
||||
}
|
||||
|
||||
private onInitIndexChange() {
|
||||
this.selectIndex(this.initIndex)
|
||||
}
|
||||
|
||||
private initGroupInfo() {
|
||||
let lastSelectIndex = this.currentIndex
|
||||
let lastGroupInfo = lastSelectIndex < this.groups.length ? this.groups[lastSelectIndex]:undefined
|
||||
if (!this.isTemporaryUser()) {
|
||||
let groups = loadCustomGroups(true)
|
||||
let defaultSelectGroupInfo = getSelfStock()
|
||||
if (defaultSelectGroupInfo.length <= 0){
|
||||
this.buildRecommendContractWhenSelfCodeNoData(lastSelectIndex,lastGroupInfo,groups)
|
||||
return
|
||||
}
|
||||
groups.unshift({
|
||||
id: FirstPageSelfCodeGroupView.GROUPID_DEFAULT,
|
||||
name: '默认',
|
||||
stocks: defaultSelectGroupInfo
|
||||
})
|
||||
this.groups = groups.slice(0, this.maxGroupCount)
|
||||
this.initGroupIndexAndNotify(lastSelectIndex, lastGroupInfo)
|
||||
} else {
|
||||
let defaultStocks = getSelfStock()
|
||||
if (defaultStocks.length > 0){
|
||||
//临时账户有添加过自选股
|
||||
let defaultGroupInfos: GroupInfo[] = []
|
||||
defaultGroupInfos.push({
|
||||
id: FirstPageSelfCodeGroupView.GROUPID_DEFAULT,
|
||||
name: '默认',
|
||||
stocks: getSelfStock()
|
||||
})
|
||||
this.groups = defaultGroupInfos
|
||||
this.initGroupIndexAndNotify(lastSelectIndex,lastGroupInfo)
|
||||
return
|
||||
}
|
||||
|
||||
this.buildRecommendContractWhenSelfCodeNoData(lastSelectIndex,lastGroupInfo)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private buildRecommendContractWhenSelfCodeNoData(lastSelectIndex:number,lastGroupInfo?:GroupInfo,customGroupInfos?:GroupInfo[]){
|
||||
RecommendContractManager.getInstance().getRecommendContract().then((result)=>{
|
||||
if (result && result.length > 0) {
|
||||
let groups:GroupInfo[] = []
|
||||
let stocks:Array<Securities> = []
|
||||
result.forEach((value:RecommendContract,index:number) =>{
|
||||
if (value.stockInfo && HXUtils.isValidContractData(value.stockInfo.code) && HXUtils.isValidContractData(value.stockInfo.market)) {
|
||||
let stock = new Securities(value.stockInfo.code,value.stockInfo.market)
|
||||
stock.name = value.stockInfo.name??"--"
|
||||
stocks.push(stock)
|
||||
}
|
||||
})
|
||||
if (customGroupInfos) {
|
||||
customGroupInfos.unshift({
|
||||
id: FirstPageSelfCodeGroupView.GROUPID_DEFAULT,
|
||||
name: '默认',
|
||||
stocks: stocks
|
||||
})
|
||||
this.groups = customGroupInfos.slice(0, this.maxGroupCount)
|
||||
this.initGroupIndexAndNotify(lastSelectIndex, lastGroupInfo)
|
||||
}else {
|
||||
groups.push({
|
||||
id:FirstPageSelfCodeGroupView.GROUPID_RECOMMEND_CONTRACT,
|
||||
name:"热门合约",
|
||||
stocks:stocks
|
||||
})
|
||||
this.groups = groups
|
||||
}
|
||||
this.initGroupIndexAndNotify(lastSelectIndex,lastGroupInfo)
|
||||
}else {
|
||||
this.groups = []
|
||||
this.initGroupIndexAndNotify(lastSelectIndex,lastGroupInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private initGroupIndexAndNotify(lastSelectIndex: number, lastGroupInfo: GroupInfo | undefined) {
|
||||
if (this.lastGroupId) {
|
||||
this.groups.forEach((group, index) => {
|
||||
if (group.id === this.lastGroupId) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (this.currentIndex >= this.groups.length) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
if (lastSelectIndex == this.currentIndex) {
|
||||
let newGroupInfo = this.currentIndex < this.groups.length ? this.groups[this.currentIndex] : undefined
|
||||
if (JSON.stringify(lastGroupInfo) != JSON.stringify(newGroupInfo)) {
|
||||
this.onGroupIndexChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private selectIndex(index: number) {
|
||||
if (this.currentIndex != index && index < this.groups.length) {
|
||||
//切换后保存当前的分组id
|
||||
const groupInfo = this.groups[index]
|
||||
this.lastGroupId = groupInfo.id
|
||||
if (groupInfo.id != FirstPageSelfCodeGroupView.GROUPID_RECOMMEND_CONTRACT) {
|
||||
//不进行热门合约的记录
|
||||
PreferenceService.putVal(FirstPageSelfCodeGroupView.SP_FILE_NAME_FIRST_PAGE_SELF_CODE_FILE_NAME,
|
||||
FirstPageSelfCodeGroupView.SP_KEY_FIRST_PAGE_SELF_CODE_LAST_GROUPID, this.lastGroupId, true)
|
||||
}
|
||||
}
|
||||
this.currentIndex = index
|
||||
if (this.totalWidth > 0) {
|
||||
let offset = 0
|
||||
let targetButtonWidth = this.itemWidthArray[index]
|
||||
for (let i = 0; i < index; i++) {
|
||||
let width = this.itemWidthArray[i]
|
||||
if (width) {
|
||||
offset += width
|
||||
}
|
||||
}
|
||||
|
||||
if (targetButtonWidth) {
|
||||
offset -= (this.totalWidth - targetButtonWidth - this.OVERLAY_WIDTH) / 2
|
||||
}
|
||||
offset = Math.max(0, offset)
|
||||
this.scroller.scrollTo({ xOffset: offset, yOffset: 0, animation: true })
|
||||
}
|
||||
}
|
||||
|
||||
//判断是否是临时账号
|
||||
private isTemporaryUser(): boolean {
|
||||
return HXUserService.getInstance()?.isTemporaryUser()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { HXLog } from 'biz_common'
|
||||
import { HQDataItemModel } from '../node/model/SelfSelectedStockModel'
|
||||
|
||||
|
||||
const TAG = "FistPageTableRowBGView"
|
||||
|
||||
@Component
|
||||
export struct FirstPageTableRowBGView {
|
||||
@ObjectLink @Watch('onDataChange') hqItemDataModel: HQDataItemModel
|
||||
@State bgOpacity: number = 0
|
||||
@State bgColor: ResourceColor = Color.Transparent
|
||||
@State startColor: string = "#ffffff"
|
||||
@State endColor: string = "#ffffff"
|
||||
private lastColor: ResourceColor = ""
|
||||
private lastChangeTime = 0
|
||||
|
||||
onDataChange() {
|
||||
HXLog.d(TAG, " FistPageTableRowBGView onDataChange this.hqItemDataModel:" +
|
||||
JSON.stringify(this.hqItemDataModel))
|
||||
|
||||
if (!this.hqItemDataModel.priceChange) {
|
||||
return
|
||||
}
|
||||
let color = this.getRiseBgColor(this.hqItemDataModel.riseFailFlag)
|
||||
if (this.lastColor.toString().length > 0 && this.lastColor == color) {
|
||||
return;
|
||||
}
|
||||
this.lastColor = color ?? ""
|
||||
let now = Date.now()
|
||||
|
||||
if (typeof color === 'string' && color.length > 0 && now - this.lastChangeTime > 500) {
|
||||
this.bgColor = color
|
||||
this.startColor = this.getStartColor(this.hqItemDataModel.riseFailFlag)
|
||||
this.endColor = this.getEndColor(this.hqItemDataModel.riseFailFlag)
|
||||
this.bgOpacity = 1
|
||||
this.lastChangeTime = now
|
||||
|
||||
animateTo({
|
||||
duration: 500,
|
||||
curve: Curve.EaseOut
|
||||
}, () => {
|
||||
this.bgOpacity = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
this.buildBackgroundView()
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildBackgroundView() {
|
||||
Row()
|
||||
.linearGradient({
|
||||
direction: GradientDirection.Left,
|
||||
colors: [[this.startColor, 0.0], [this.endColor, 1.0]]
|
||||
})
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
.opacity(this.bgOpacity)
|
||||
.onAppear(() => {
|
||||
this.onDataChange()
|
||||
})
|
||||
.onDisAppear(() => {
|
||||
this.bgOpacity = 0
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private getRiseBgColor(riseFlag: number): string {
|
||||
if (riseFlag == 0) {
|
||||
return "#323232"
|
||||
}
|
||||
return riseFlag == 1 ? "#e93030" : "#009900"
|
||||
}
|
||||
|
||||
private getStartColor(riseFlag: number): string {
|
||||
if (riseFlag == 0) {
|
||||
return "#FFFFFF"
|
||||
}
|
||||
return riseFlag == 1 ? "#00FF2436" : "#0007ab4b"
|
||||
}
|
||||
|
||||
private getEndColor(riseFlag: number): string {
|
||||
if (riseFlag == 0) {
|
||||
return "#FFFFFF"
|
||||
}
|
||||
return riseFlag == 1 ? "#33ff2436" : "#3307ab4b"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
import { CommonToast, GlobalContext } from 'biz_common';
|
||||
import { getUserAvatarUrlByUid, LoginUtils } from 'biz_login';
|
||||
import router from '@ohos.router';
|
||||
import { TITLE_BAR_HEIGHT } from '../util/FirstPageConstant';
|
||||
import { HXUserService } from 'biz_hxservice';
|
||||
import { AppUtil } from '@pura/harmony-utils';
|
||||
|
||||
@Component
|
||||
export default struct FirstPageTitleBar {
|
||||
//用户userid,从根节点传入
|
||||
@Consume userId: string;
|
||||
//用户userName,从根节点传入
|
||||
@Consume userName: string;
|
||||
customToast: CustomDialogController = new CustomDialogController({
|
||||
builder: CommonToast({ textContent: '体验版本功能暂未开放' }),
|
||||
alignment: DialogAlignment.Center,
|
||||
customStyle: true,
|
||||
});
|
||||
private showMessageTips: boolean = false
|
||||
|
||||
build() {
|
||||
Stack({ alignContent: Alignment.TopStart }) {
|
||||
Column() {
|
||||
Row()
|
||||
.width('100%')
|
||||
.height(px2vp(GlobalContext.statusBarHeight))
|
||||
.flexShrink(0)
|
||||
Flex({ alignItems: ItemAlign.Center }) {
|
||||
Column() {
|
||||
Image(this.isTempUser(this.userName) ? $r('app.media.user_no_login') : getUserAvatarUrlByUid(this.userId))
|
||||
.width(24)
|
||||
.height(24)
|
||||
.borderRadius(12)
|
||||
.flexShrink(0)
|
||||
.alt($r("app.media.user_no_login"))
|
||||
}
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.height('100%')
|
||||
.width(24)
|
||||
.onClick(() => {
|
||||
LoginUtils.gotoZone()
|
||||
})
|
||||
|
||||
this.searchBar()
|
||||
this.agentIcon()
|
||||
this.messageIcon()
|
||||
|
||||
}
|
||||
.padding({ left: 16, right: 16 })
|
||||
.height(TITLE_BAR_HEIGHT)
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.zIndex(1)
|
||||
|
||||
Column() {
|
||||
}
|
||||
.backgroundColor($r('app.color.surface_layer1_foreground'))
|
||||
.width('100%')
|
||||
.height(px2vp(GlobalContext.statusBarHeight) + TITLE_BAR_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
messageIcon() {
|
||||
Stack({ alignContent: Alignment.TopEnd }) {
|
||||
Image($r("app.media.icon_mail_24"))
|
||||
.fillColor($r('app.color.elements_icon_primary_02'))
|
||||
.width('100%')
|
||||
.height('100%');
|
||||
|
||||
Circle()
|
||||
.width(3)
|
||||
.height(3)
|
||||
.stroke(Color.Red)
|
||||
.fill(Color.Red)
|
||||
.margin(3)
|
||||
.visibility(this.showMessageTips ? Visibility.Visible : Visibility.None);
|
||||
}.width(24).height(24).onClick(() => {
|
||||
this.onMessageClick()
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
agentIcon() {
|
||||
Stack({ alignContent: Alignment.TopEnd }) {
|
||||
Image($r("app.media.icon_bot_24"))
|
||||
.fillColor($r('app.color.elements_icon_primary_02'))
|
||||
.width('100%')
|
||||
.height('100%');
|
||||
|
||||
Circle()
|
||||
.width(3)
|
||||
.height(3)
|
||||
.stroke(Color.Red)
|
||||
.fill(Color.Red)
|
||||
.margin({ left: 3})
|
||||
.visibility(this.showMessageTips ? Visibility.Visible : Visibility.None);
|
||||
}.width(24).height(24).margin({ right: 10 }).onClick(() => {
|
||||
this.onAgentClick()
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
searchBar() {
|
||||
Row() {
|
||||
Image($r('app.media.icon_search_24'))
|
||||
.width(18)
|
||||
.height(18)
|
||||
.fillColor($r('app.color.elements_icon_tertiary'))
|
||||
|
||||
|
||||
Text("请输入代码/名称/简称")
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.elements_text_quaternary'))
|
||||
.margin({ left: 4 })
|
||||
}
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.margin({
|
||||
top: 8,
|
||||
bottom: 8,
|
||||
left: 14,
|
||||
right: 14
|
||||
})
|
||||
.padding({ left: 8 })
|
||||
.height(28)
|
||||
.layoutWeight(1)
|
||||
.backgroundColor($r('app.color.elements_others_bg_layer1'))
|
||||
.borderRadius(25)
|
||||
.flexGrow(1)
|
||||
.onClick(() => {
|
||||
router.pushUrl({
|
||||
url: 'pages/SearchPage' // 目标url
|
||||
}, router.RouterMode.Standard, (err) => {
|
||||
if (err) {
|
||||
console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
|
||||
return;
|
||||
}
|
||||
console.info('Invoke pushUrl succeeded.');
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
private isTempUser(userName: string): boolean {
|
||||
return userName.length > 0 && userName.startsWith("mt_");
|
||||
}
|
||||
|
||||
private onMessageClick() {
|
||||
if (this.autoLogin()) {
|
||||
return
|
||||
}
|
||||
router.pushUrl({
|
||||
url: 'pages/WebViewComponentPage', params: {
|
||||
url: 'https://fupage.10jqka.com.cn/projects/m/message/index.html',
|
||||
title: '消息中心',
|
||||
updateH5Title: '0'
|
||||
}
|
||||
},
|
||||
router.RouterMode.Single, (err) => {
|
||||
if (err) {
|
||||
console.error(`go to message page failed , cause : ${err.message}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private onAgentClick() {
|
||||
if (this.autoLogin()) {
|
||||
return
|
||||
}
|
||||
router.pushUrl({
|
||||
url: 'pages/WebViewComponentPage', params: {
|
||||
url:AppUtil.getContext().resourceManager.getStringSync($r('app.string.fu_feed_back_help_url')),
|
||||
title: AppUtil.getContext().resourceManager.getStringSync($r('app.string.feed_back_help_text')),
|
||||
userCookie:true,
|
||||
isLoginRefreshWeb:true,
|
||||
refreshOnWidthChange:true
|
||||
}
|
||||
},
|
||||
router.RouterMode.Single, (err) => {
|
||||
if (err) {
|
||||
console.error(`go to message page failed , cause : ${err.message}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private autoLogin(): boolean {
|
||||
if (!HXUserService.getInstance().isLoggedIn()) {
|
||||
const topRoutePath = router.getState().path
|
||||
router.pushUrl({
|
||||
url: 'pages/login/LoginPage',
|
||||
params: {
|
||||
flexSwitchFlag: true,
|
||||
sourcePage: `${topRoutePath}${router.getState().name}`
|
||||
}
|
||||
})
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { ScreenUtils } from '@b2b/hxutil'
|
||||
import { ColorUtils } from '@b2c/lib_baseui'
|
||||
import { TextMetricsMeasurer } from '@b2b/hq_table'
|
||||
import { HQDataItemModel } from '../node/model/SelfSelectedStockModel'
|
||||
import { FirstPageTableRowBGView } from './FirstPageTableRowBGView'
|
||||
|
||||
|
||||
@Component
|
||||
export struct FistPageSelfCodeGridItemView {
|
||||
@ObjectLink hqItemData: HQDataItemModel
|
||||
|
||||
jumpToQuoteCallBack?: (tockModel: HQDataItemModel) => void
|
||||
jumpToMoreCallBack?:()=>void
|
||||
|
||||
|
||||
|
||||
build() {
|
||||
this.buildStockItem(this.hqItemData)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildStockItem(stockModel: HQDataItemModel) {
|
||||
if (!stockModel.showAddImage) {
|
||||
Column() {
|
||||
Text(stockModel.name)
|
||||
.minFontSize(10)
|
||||
.maxFontSize(this.getAvailableFontSize(stockModel.name))
|
||||
.fontColor($r('app.color.elements_text_primary_02'))
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.maxLines(1)
|
||||
.margin({ bottom: 4 })
|
||||
.width('100%')
|
||||
Column(){
|
||||
Stack(){
|
||||
FirstPageTableRowBGView({
|
||||
hqItemDataModel: stockModel
|
||||
})
|
||||
Text(stockModel.price.toString())
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(ColorUtils.resourceColorToRGBHex(stockModel.riseFailColor))
|
||||
.margin({ bottom: 2 })
|
||||
}.alignContent(Alignment.Start)
|
||||
}.width('100%')
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.height(25)
|
||||
|
||||
Row() {
|
||||
Text(stockModel.priceRise)
|
||||
.fontSize(11)
|
||||
.fontColor(ColorUtils.resourceColorToRGBHex(stockModel.riseFailColor))
|
||||
.margin({ right: 4 })
|
||||
|
||||
Text(`${stockModel.riseFail}`)
|
||||
.fontSize(11)
|
||||
.fontColor(ColorUtils.resourceColorToRGBHex(stockModel.riseFailColor))
|
||||
}
|
||||
}
|
||||
.border({
|
||||
width: { right: 1 }, // 只画右边框
|
||||
color: $r('app.color.elements_others_divider_primary'),
|
||||
style: BorderStyle.Solid
|
||||
|
||||
})
|
||||
.onClick(() => {
|
||||
this.jumpToQuote(stockModel)
|
||||
})
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor(Color.Transparent)
|
||||
.padding(10)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
} else {
|
||||
this.buildMoreItem()
|
||||
}
|
||||
}
|
||||
|
||||
jumpToQuote(stockModel: HQDataItemModel) {
|
||||
if (this.jumpToQuoteCallBack) {
|
||||
this.jumpToQuoteCallBack(stockModel)
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildMoreItem() {
|
||||
Column() {
|
||||
Column(){
|
||||
Image($r('app.media.icon_add_24'))
|
||||
.fillColor($r('app.color.elements_icon_secondary'))
|
||||
.width(20)
|
||||
.height(20)
|
||||
} .width('100%')
|
||||
.height('100%')
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.border({
|
||||
width: 1, // 只画右边框
|
||||
color: $r('app.color.elements_others_border_base'),
|
||||
style: BorderStyle.Dashed,
|
||||
dashGap:{value:3,unit:1},
|
||||
radius:4
|
||||
})
|
||||
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor($r('app.color.surface_layer1_foreground'))
|
||||
.padding(8)
|
||||
.borderRadius(4)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.onClick(() => {
|
||||
this.jumpToMore()
|
||||
})
|
||||
}
|
||||
|
||||
jumpToMore() {
|
||||
if (this.jumpToMoreCallBack) {
|
||||
this.jumpToMoreCallBack()
|
||||
}
|
||||
}
|
||||
|
||||
private getAvailableFontSize(name: string): number {
|
||||
return TextMetricsMeasurer.getInstance().matchFontSize(name, (ScreenUtils.getScreenWidth(true) - 20) / 3 - 22, 14)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { GlobalContext } from 'biz_common';
|
||||
|
||||
@Component
|
||||
export struct StatusBar {
|
||||
@Prop bgColor:string | ResourceColor = $r('app.color.surface_layer1_foreground')
|
||||
|
||||
build(){
|
||||
Row()
|
||||
.width('100%')
|
||||
.height(px2vp(GlobalContext.statusBarHeight))
|
||||
.backgroundColor(this.bgColor)
|
||||
.flexShrink(0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import { router } from '@kit.ArkUI'
|
||||
import { StatusBar } from './StatusBar'
|
||||
|
||||
@Component
|
||||
export struct TitleBar {
|
||||
|
||||
showStatusBar: boolean = false
|
||||
@Prop statusBarBgColor:string
|
||||
@Prop title: string
|
||||
titleColor: ResourceColor = $r('app.color.elements_text_primary_02')
|
||||
bgColor: ResourceColor = $r('app.color.surface_layer1_foreground')
|
||||
leftWidth: number = 0
|
||||
rightWidth: number = 0
|
||||
@State leftMarginWidth: number = 0
|
||||
@State rightMarginWidth: number = 0
|
||||
@State showRefresh: boolean = false
|
||||
onRefresh?: (() => void) | null
|
||||
@BuilderParam buildLeftView?: (() => void) | null
|
||||
@BuilderParam buildRightView?: (() => void) | null
|
||||
|
||||
private calculateMiddleMargin() {
|
||||
let space = Math.abs(this.leftWidth - this.rightWidth)
|
||||
if (this.leftWidth > this.rightWidth) {
|
||||
this.leftMarginWidth = 0
|
||||
this.rightMarginWidth = space
|
||||
} else if (this.leftWidth < this.rightWidth) {
|
||||
this.leftMarginWidth = space
|
||||
this.rightMarginWidth = 0
|
||||
} else {
|
||||
this.leftMarginWidth = 0
|
||||
this.rightMarginWidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
if (this.showStatusBar) {
|
||||
StatusBar({
|
||||
bgColor: this.statusBarBgColor
|
||||
})
|
||||
}
|
||||
Row() {
|
||||
Row() {
|
||||
if (this.buildLeftView) {
|
||||
this.buildLeftView()
|
||||
} else {
|
||||
this.buildBackView()
|
||||
}
|
||||
}
|
||||
.height('100%')
|
||||
.onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => {
|
||||
this.leftWidth = newValue.width as number
|
||||
this.calculateMiddleMargin()
|
||||
})
|
||||
|
||||
Text(this.title)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.fontSize(16)
|
||||
.fontColor(this.titleColor)
|
||||
.textAlign(TextAlign.Center)
|
||||
.maxLines(1)
|
||||
.textOverflow({overflow: TextOverflow.Ellipsis})
|
||||
.layoutWeight(1)
|
||||
.margin({left: this.leftMarginWidth, right: this.rightMarginWidth})
|
||||
|
||||
Row() {
|
||||
if (this.buildLeftView) {
|
||||
this.buildLeftView()
|
||||
} else {
|
||||
this.buildRefreshView()
|
||||
}
|
||||
}
|
||||
.height('100%')
|
||||
.onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => {
|
||||
this.rightWidth = newValue.width as number
|
||||
this.calculateMiddleMargin()
|
||||
})
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.width('100%')
|
||||
.height(42)
|
||||
.backgroundColor(this.bgColor)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildBackView() {
|
||||
Column() {
|
||||
Image($r('app.media.icon_arrow_left_24'))
|
||||
.fillColor($r('app.color.elements_icon_primary_02'))
|
||||
.width(19)
|
||||
.height(24)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width(40)
|
||||
.height('100%')
|
||||
.onClick(() => {
|
||||
router.back()
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildRefreshView() {
|
||||
if (this.showRefresh) {
|
||||
Column() {
|
||||
Image($r('app.media.title_bar_refresh'))
|
||||
.width(20)
|
||||
.height(20)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.width(40)
|
||||
.height('100%')
|
||||
.onClick(() => {
|
||||
if (this.onRefresh) {
|
||||
this.onRefresh()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user