99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何在鴻蒙系統(tǒng)弄一個(gè)彩票查詢(xún)卡片

OpenHarmony技術(shù)社區(qū) ? 來(lái)源:HarmonyOS技術(shù)社區(qū) ? 作者:中軟國(guó)際 ? 2021-09-06 09:17 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

接觸鴻蒙開(kāi)發(fā)已經(jīng)有 3 個(gè)來(lái)月了,最近開(kāi)始在看鴻蒙卡片開(kāi)發(fā)。因?yàn)橹暗拈_(kāi)發(fā)大都是基于 Java UI,但按官方的說(shuō)法,JS 卡片相比 Java 卡片有更大的優(yōu)勢(shì),故決定寫(xiě)個(gè) JS 卡片的 demo 來(lái)練練手。

碰巧,前幾天和媳婦兒在散步時(shí)撿到 1 元錢(qián),沒(méi)能交給警察叔叔,媳婦兒就提議“我們把它昧了吧,買(mǎi)張彩票。”

由于不是老 CM,沒(méi)有關(guān)注開(kāi)獎(jiǎng)的習(xí)慣,想著要是能把開(kāi)獎(jiǎng)結(jié)果放在手機(jī)桌面顯示就好了,這樣就不會(huì)錯(cuò)過(guò)我一夜暴富的機(jī)會(huì)了。有了需求就開(kāi)擼,然后就有了這篇文章!

項(xiàng)目簡(jiǎn)介

①本項(xiàng)目基于 API 6 開(kāi)發(fā),demo 運(yùn)行在 API 6 以下的手機(jī)上會(huì)出現(xiàn)部分功能不能使用的現(xiàn)象。

②卡片功能上實(shí)現(xiàn)了***、福彩 3D 的最近一期開(kāi)獎(jiǎng)結(jié)果查詢(xún),點(diǎn)擊卡片“刷新”按鈕,調(diào)用接口更新最新數(shù)據(jù);點(diǎn)擊“查看更多”按鈕,跳轉(zhuǎn)至應(yīng)用主界面。

③應(yīng)用主界面上實(shí)現(xiàn)了***、福彩 3D 近 50 期開(kāi)獎(jiǎng)結(jié)果查看。

④以上數(shù)據(jù)均使用了聚合數(shù)據(jù)的 https://www.juhe.cn/docs/api/id/300 免費(fèi)接口。

需申請(qǐng) key,一個(gè) key 一天可免費(fèi)調(diào)用 100 次,如遇 key使 用次數(shù)過(guò)多導(dǎo)致接口請(qǐng)求失敗情況時(shí),開(kāi)發(fā)者可自行申請(qǐng) key 并替換 Constants.java 文件下的 JH_KEY 常量值),數(shù)據(jù)可能會(huì)有延遲。

⑤卡片開(kāi)發(fā)部分使用了卡片的 JS UI 框架,但由于系統(tǒng) PA 與 FA 相互調(diào)用的限制問(wèn)題,卡片的業(yè)務(wù)邏輯部分仍然采用 Java 代碼編寫(xiě)。

PS:最開(kāi)始的想法是盡量可能的少依賴(lài) Java 代碼,故嘗試了 JS FA 與 Java PA 相互調(diào)用的方式,但當(dāng)應(yīng)用進(jìn)程被干掉時(shí),Java 端無(wú)法再調(diào)用到 JS 端方法。

這樣就導(dǎo)致 JS 只能寫(xiě) UI 部分,業(yè)務(wù)邏輯還得 Java 層實(shí)現(xiàn)。有知道解決辦法的也麻煩告知一聲。

⑥卡片業(yè)務(wù)層使用 Java 開(kāi)發(fā),采用了簡(jiǎn)單的 MVP 架構(gòu),網(wǎng)絡(luò)請(qǐng)求和數(shù)據(jù)處理部分使用了 rxjava3+retrofit 框架。

⑦應(yīng)用主界面使用了 JS-UI 框架實(shí)現(xiàn)。

實(shí)現(xiàn)效果

請(qǐng)忽略我粗陋的 UI 設(shè)計(jì)和 GIF 的渣渣像素。

項(xiàng)目代碼結(jié)構(gòu)分析

base:

IBasePresenter:MVP 架構(gòu)中 presenter 基類(lèi)接口

IBaseView:MVP 架構(gòu)中 view 基類(lèi)接口

network:

bean,LotteryBean:彩票詳情接口返回對(duì)應(yīng) model

CachedLotteryDetailUtil:彩票詳情接口請(qǐng)求工具類(lèi),主要作用是防止重復(fù)調(diào)用詳情接口

LogInterceptor:OKhttp 日志攔截工具類(lèi)

LotteryAPI:接口請(qǐng)求類(lèi),通過(guò) retrofit 注解,將接口返回?cái)?shù)據(jù)轉(zhuǎn)化為實(shí)體類(lèi)

Services:配置 Retrofit 并提供

presenter:

IMainContract:MVP 中 view 與 presenter 的橋梁

MainPresenter:提供彩票詳情接口的請(qǐng)求,并處理接口返回?cái)?shù)據(jù)為卡片需要的 ZSONObject 對(duì)象

utils:

LogUtil:日志打印工具類(lèi)

widget:

controller:FormController:創(chuàng)建卡片時(shí)自動(dòng)生成,卡片管理器的抽象基類(lèi);FormControllerManager:創(chuàng)建卡片時(shí)自動(dòng)生成,管理各個(gè) FormController 的工具類(lèi)

dltwidget.DltWidgetImpl:大樂(lè)透卡片管理類(lèi),提供了創(chuàng)建卡片、更新卡片、刪除卡片、卡片點(diǎn)擊事件等行為的回調(diào)方法

fcsdwidget.FcsdWidgetImpl:福彩 3D 卡片管理類(lèi),提供了創(chuàng)建卡片、更新卡片、刪除卡片、卡片點(diǎn)擊事件等行為的回調(diào)方法

ssqwidget.SsqWidgetImpl:雙色球卡片管理類(lèi),提供了創(chuàng)建卡片、更新卡片、刪除卡片、卡片點(diǎn)擊事件等行為的回調(diào)方法

Constants:常量工具類(lèi)。

MainAbility:HAP 的入口 ability,由 DevEco Studio 自動(dòng)生成。同時(shí)也是各個(gè)卡片對(duì)應(yīng)的 Ability,用來(lái)項(xiàng)各個(gè) FormController 分發(fā)事件。

default:

common,component/lottery:應(yīng)用首頁(yè)列表 item 組件;images :資源圖片

pages,home:應(yīng)用首頁(yè)

dlt_widget:

common:資源圖片存放目錄

pages/index,index.css :大樂(lè)透卡片 css 樣式;index.hml:大樂(lè)透卡片布局文件;index.json:包含頁(yè)面默認(rèn)值

fcsd_widget:目錄結(jié)構(gòu)同 dlt_widget。

ssq_widget:目錄結(jié)構(gòu)同 dlt_widget。

詳細(xì)實(shí)現(xiàn)過(guò)程

①創(chuàng)建雙色球卡片

在目錄 entry 上點(diǎn)擊右鍵,在彈出的菜單中選擇 New,然后在彈出的子菜單中點(diǎn)擊 Service Widget,如下圖所示:

在模板選擇界面,選擇基本的模板 Grid Pattern,點(diǎn)擊按鈕 Next,進(jìn)入到卡片配置界面:

首先配置卡片的名稱(chēng)和描述;然后配置卡片關(guān)聯(lián)的 Page Ability;然后配置卡片的編程語(yǔ)言類(lèi)型是 JS;接下來(lái)配置卡片的 JS 組件名稱(chēng);最后配置卡片支持的規(guī)格,勾選支持 2x4、4x4 規(guī)格。

重復(fù)上述步驟,創(chuàng)建出大樂(lè)透和雙色球卡片。運(yùn)行項(xiàng)目,長(zhǎng)按圖標(biāo)打開(kāi)卡片管理界面,我們能看到剛創(chuàng)建的 3 類(lèi)卡片,且每類(lèi)卡片對(duì)應(yīng) 3 種不同樣式,如下圖所示:

②繪制雙色球卡片 UI

我們編寫(xiě)雙色球界面:

《!--index.hml--》《div class=“container”》

《div》

《text class=“text”》雙色球《/text》

《text class=“text-small” style=“margin-left : 15px;” if=“{{ cardType2x4 || cardType4x4 }}”》每周二、四、日開(kāi)獎(jiǎng)《/text》

《text class=“text” style=“margin-left : 75px;” if=“{{ cardType2x4 || cardType4x4 }}” onclick=“showMore”》 查看更多

《/text》

《/div》

《div style=“margin-top : 10px; align-content : center;”》

《text class=“text-small” style=“margin-right : 10px;”》第{{ lotteryData.lottery_no }}期《/text》

《text class=“text-small” if=“{{ cardType2x4 || cardType4x4 }}”》 開(kāi)獎(jiǎng)日期:《/text》

《text class=“text-small”》 {{ lotteryData.lottery_date }}《/text》

《/div》

《div style=“flex-wrap : wrap; margin-top : 10px;”》

《text class=“ball” for=“{{ lotteryRed }}” tid=“id”》{{ $item }}《/text》

《text class=“ball” style=“background-color : blue;” for=“{{ lotteryBlue }}” tid=“id”》{{ $item }}《/text》

《/div》

《div class=“amount-box” if=“{{ cardType2x4 || cardType4x4 }}”》

《div style=“flex-direction : column;”》

《text class=“text-small”》本期全國(guó)銷(xiāo)量《/text》

《text class=“text-amount”》{{ lotteryData.lottery_sale_amount }}《/text》

《/div》

《text class=“diver”》《/text》

《div style=“flex-direction : column;”》

《text class=“text-small”》累計(jì)獎(jiǎng)池《/text》

《text class=“text-amount”》{{ lotteryData.lottery_pool_amount }}《/text》

《/div》

《/div》

《div style=“flex-direction : column; padding-top : 10px; margin-bottom: 20px;” if=“{{ cardType4x4 }}”》

《div style=“background-color : green;”》

《text class=“text-prize”》獎(jiǎng)項(xiàng)《/text》

《text class=“text-prize”》中獎(jiǎng)條件《/text》

《text class=“text-prize”》中獎(jiǎng)注數(shù)《/text》

《text class=“text-prize”》單注金額(元)《/text》

《/div》

《div for=“{{ lottery_prize }}”》

《text class=“text-prize”》{{ $item.prize_name }}《/text》

《text class=“text-prize”》{{ $item.prize_require }}《/text》

《text class=“text-prize”》{{ $item.prize_num }}《/text》

《text class=“text-prize”》{{ $item.prize_amount }}《/text》

《/div》

《/div》

《div》

《text class=“text-small” if=“{{ cardType2x4 || cardType4x4 }}”》更新時(shí)間:《/text》

《text class=“text-small”》{{ updateTime }}《/text》

《image class=“refresh” src=“/common/image_1.png” onclick=“updateData”》《/image》

《/div》《/div》

《!--index.json--》

{

“data”: {

“cardType2x2”: true,

“cardType2x4”: false,

“cardType4x4”: false,

“l(fā)otteryData”: {

“l(fā)ottery_no”: “21081”,

“l(fā)ottery_date”: “2021-07-20”,

“l(fā)ottery_sale_amount”:“344,437,194”,

“l(fā)ottery_pool_amount”:“997,378,346”

},

“l(fā)otteryRed”:[“01”,“03”,“05”,“18”,“22”,“23”],

“l(fā)otteryBlue”:[“01”],

“updateTime”: “2021/07/07 1459”,

“l(fā)ottery_prize”:[

{

“prize_name”:“一等獎(jiǎng)”,

“prize_num”:“4”,

“prize_amount”:“10,000,000”,

“prize_require”:“6+1”

},

{

“prize_name”:“二等獎(jiǎng)”,

“prize_num”:“135”,

“prize_amount”:“207,725”,

“prize_require”:“6+0”

},

{

“prize_name”:“三等獎(jiǎng)”,

“prize_num”:“879”,

“prize_amount”:“3,000”,

“prize_require”:“5+1”

},

{

“prize_name”:“四等獎(jiǎng)”,

“prize_num”:“45659”,

“prize_amount”:“200”,

“prize_require”:“5+0,4+1”

},

{

“prize_name”:“五等獎(jiǎng)”,

“prize_num”:“1001881”,

“prize_amount”:“10”,

“prize_require”:“4+0,3+1”

},

{

“prize_name”:“六等獎(jiǎng)”,

“prize_num”:“6962930”,

“prize_amount”:“5”,

“prize_require”:“2+1,1+1,0+1”

}

},

“actions”: {

}

}

《!--index.css--》

.container {

width: 100%;

height: 100%;

padding: 10px;

flex-direction: column;

}

.text {

font-size: 15px;

}

.text-small {

font-size: 11px;

}

.text-amount {

font-size: 14px;

font-weight: bold;

color: darkred;

}

.text-prize {

font-size: 11px;

flex-weight: 25;

min-height: 20px;

text-align: center;

}

.ball {

width: 20px;

height: 20px;

text-align: center;

font-size: 12px;

margin: 4px;

color: #FFFFFF;

border-radius: 20px;

background-color: red;

}

.amount-box {

flex-direction: row;

align-items: center;

height: 30px;

}

.diver {

width: 1px;

height: 20px;

background-color: red;

margin-left: 15px;

margin-right: 15px;

}

.refresh {

width: 22px;

height: 22px;

}

編寫(xiě)完成后,重新運(yùn)行,不出意外你應(yīng)該能看到如下效果:

這里提下卡片 JS-UI 框架的坑:

框架提供了原子布局來(lái)控制元素在不同尺寸布局上的隱藏和展示,但怎么說(shuō)呢 ,一句話(huà)概括就是:你以為的并不是你以為的。

可以看到我這里放棄了 display-index 的使用,而采用通過(guò) JAVA 端卡片的類(lèi)型,來(lái)適配不同的 UI。

不同于應(yīng)用開(kāi)發(fā)中的 JS UI 框架,這里的條件渲染不支持表達(dá)式。

css 不支持標(biāo)簽選擇器。

部分 css 樣式不能被繼承,例如給父 div 元素設(shè)置了 font-size,你會(huì)發(fā)現(xiàn) div 中的 text 組件并沒(méi)繼承上述樣式。

列表渲染的 for 循環(huán)的數(shù)組必須是 index.json data 對(duì)象的最外層。

不支持雙層 for 循環(huán)。

api6 不兼容 api5 的設(shè)備。

你會(huì)發(fā)現(xiàn)卡片 JSON 文件中的 data 對(duì)象數(shù)據(jù)結(jié)構(gòu)同接口返回的數(shù)據(jù)結(jié)構(gòu)有些差異,就是因?yàn)樯鲜鲈驅(qū)е碌摹?/p>

③獲取網(wǎng)絡(luò)數(shù)據(jù)

簡(jiǎn)單的 MVP 架構(gòu),采用 Retrofit+RxJava 作為異步網(wǎng)絡(luò)請(qǐng)求框架。

build.gradle 中添加 RxJava 和 Retrofit 的依賴(lài):

// RxJava

api ‘io.reactivex.rxjava33.0.3’

implementation ‘io.openharmony.tpc.thirdlib1.0.0’// retrofit

implementation ‘com.squareup.retrofit22.7.0’

implementation “com.squareup.retrofit22.1.0”

implementation ‘com.squareup.retrofit22.9.0’

config.json 文件中添加網(wǎng)絡(luò)權(quán)限:

// config.json“deviceConfig”: {

“default”: {

“network”: {

“cleartextTraffic”: true,

“securityConfig”: {

“domainSettings”: {

“cleartextPermitted”: true,

“domains”: [

{

subdomains”: true,

“name”: “apis.juhe.cn”

},

{

“subdomains”: true,

“name”: “v.juhe.cn”

}

}

}

}

}

},

“module”: {

。..

“reqPermissions”: [

{

“name”: “ohos.permission.GET_NETWORK_INFO”

},

{

“name”: “ohos.permission.SET_NETWORK_INFO”

},

{

“name”: “ohos.permission.INTERNET”

}

],

。..

}

創(chuàng)建接口請(qǐng)求:

// LotteryAPI.javapublic interface LotteryAPI {

@POST(“/lottery/query”)

@FormUrlEncoded

Observable《LotteryBean》 queryDetail(@Field(“l(fā)ottery_id”) String lottery_id, @Field(“l(fā)ottery_no”) String lottery_no, @Field(“key”) String key);

}

P 層和 V 層的接口比較簡(jiǎn)單,不在羅列。編寫(xiě) P 層業(yè)務(wù)邏輯:

//MainPresenter.java@Overridepublic void loadLotteryData(long formId, String lotteryId) {

CachedLotteryDetailUtil.getLotteryDetail(lotteryId)

.flatMap((Function《LotteryBean, ObservableSource《ZSONObject》》) res -》 {

if (0 != res.getError_code()) {

Throwable throwable = new Throwable(res.getReason());

return Observable.error(throwable);

}

ZSONObject zsonObject = buildDataByResult(res);

return Observable.just(zsonObject);

})

.subscribeOn(Schedulers.io())

.observeOn(OpenHarmonySchedulers.mainThread())

.subscribe(new Observer《ZSONObject》() {

@Override

public void onSubscribe(@NonNull Disposable d) {

}

@Override

public void onNext(@NonNull ZSONObject result) {

if (mView != null) {

mView.onLoadDataSuccess(formId, result);

}

}

@Override

public void onError(@NonNull Throwable e) {

if (mView != null) {

mView.onLoadDataFailed(e);

}

}

@Override

public void onComplete() {

}

});

}

/**

* 根據(jù)接口返回的數(shù)據(jù),組裝成JS卡片需要的數(shù)據(jù)

*

* @param result

* @return

*/private ZSONObject buildDataByResult(LotteryBean result) {

LotteryBean.DetailBean detailBean = result.getResult();

ZSONObject data = new ZSONObject();

ZSONObject lotteryData = new ZSONObject();

lotteryData.put(“l(fā)ottery_no”, detailBean.getLottery_no());

lotteryData.put(“l(fā)ottery_date”, detailBean.getLottery_date());

lotteryData.put(“l(fā)ottery_sale_amount”, detailBean.getLottery_sale_amount());

lotteryData.put(“l(fā)ottery_pool_amount”, detailBean.getLottery_pool_amount());

data.put(“l(fā)otteryData”, lotteryData);

String[] ballArray = detailBean.getLottery_res().split(“,”);

if (“ssq”.equalsIgnoreCase(detailBean.getLottery_id())){

data.put(“l(fā)otteryRed”, Arrays.copyOfRange(ballArray, 0, 6));

data.put(“l(fā)otteryBlue”, Arrays.copyOfRange(ballArray, 6, 7));

} else if (“dlt”.equalsIgnoreCase(detailBean.getLottery_id())){

data.put(“l(fā)otteryRed”, Arrays.copyOfRange(ballArray, 0, 5));

data.put(“l(fā)otteryBlue”, Arrays.copyOfRange(ballArray, 5, 7));

} else if (“fcsd”.equalsIgnoreCase(detailBean.getLottery_id())){

data.put(“l(fā)otteryRed”, ballArray);

}

data.put(“updateTime”, new SimpleDateFormat(“yyyy-MM-dd HHss”).format(new Date()));

ZSONArray zsonArray = new ZSONArray();

for (LotteryBean.PrizeBean prizeBean : detailBean.getLottery_prize()) {

ZSONObject prize = new ZSONObject();

prize.put(“prize_name”, prizeBean.getPrize_name());

prize.put(“prize_num”, prizeBean.getPrize_num());

prize.put(“prize_amount”, prizeBean.getPrize_amount());

prize.put(“prize_require”, prizeBean.getPrize_require());

zsonArray.add(prize);

}

data.put(“l(fā)ottery_prize”, zsonArray);

return data;

}

④V 層調(diào)用 P 層,更新卡片

這里提下 MainAbility 的 onCreateForm 方法,它在進(jìn)入卡片管理界面時(shí)被調(diào)用,內(nèi)部通過(guò) FormControllerManager 獲取了卡片對(duì)應(yīng)的 FormController,并調(diào)用了其 bindFormData() 方法。

由于我們卡片展示的數(shù)據(jù)來(lái)源于網(wǎng)絡(luò)請(qǐng)求,在對(duì)應(yīng)的 FormController 實(shí)現(xiàn)類(lèi)中不太好獲得 formId,所以我們稍微改造一下 FormController 的 bindFormData 方法,把 formId 給傳進(jìn)去。

public abstract ProviderFormInfo bindFormData(long formId);

//MainAbility.javapublic class MainAbility extends AceAbility implements IMainContract.View {

private IMainContract.Presenter mPresenter;

@Override

public void onStart(Intent intent) {

。..

}

@Override

public void onStop() {

super.onStop();

}

@Override

protected ProviderFormInfo onCreateForm(Intent intent) {

HiLog.info(TAG, “onCreateForm”);

long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);

String formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);

int dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);

HiLog.info(TAG, “onCreateForm: formId=” + formId + “,formName=” + formName);

FormControllerManager formControllerManager = FormControllerManager.getInstance(this);

FormController formController = formControllerManager.getController(formId);

formController = (formController == null) ? formControllerManager.createFormController(formId,

formName, dimension) : formController;

if (formController == null) {

HiLog.error(TAG, “Get null controller. formId: ” + formId + “, formName: ” + formName);

return null;

}

return formController.bindFormData(formId);

}

@Override

protected void onUpdateForm(long formId) {

。..

}

@Override

protected void onDeleteForm(long formId) {

。..

}

@Override

protected void onTriggerFormEvent(long formId, String message) {

。..

}

@Override

public void onNewIntent(Intent intent) {

。..

}

private boolean intentFromWidget(Intent intent) {

。..

}

private String getRoutePageSlice(Intent intent) {

。..

}

private IMainContract.Presenter getPresenter() {

if (mPresenter == null) {

mPresenter = new MainPresenter(this);

}

return mPresenter;

}

/**

* 查詢(xún)彩票開(kāi)獎(jiǎng)詳情

*

* @param formId

* @param lotteryId

*/

public void loadData(long formId, String lotteryId) {

getPresenter().loadLotteryData(formId, lotteryId);

}

@Override

public void onLoadDataSuccess(long formId, ZSONObject data) {

try {

// 更新卡片

updateForm(formId, new FormBindingData(data));

} catch (FormException e) {

e.printStackTrace();

}

}

@Override

public void onLoadDataFailed(Throwable exception) {

。..

}

}

//SsqWidgetImpl.javapublic class SsqWidgetImpl extends FormController{

private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, SsqWidgetImpl.class.getName());

public SsqWidgetImpl(Context context, String formName, Integer dimension) {

super(context, formName, dimension);

}

@Override

public ProviderFormInfo bindFormData(long formId) {

HiLog.info(TAG, “===== ssq bind form data”);

ZSONObject zsonObject = new ZSONObject();

ProviderFormInfo providerFormInfo = new ProviderFormInfo();

boolean is2x2 = dimension == DEFAULT_DIMENSION_2X2;

boolean is2x4 = dimension == DIMENSION_2X4;

boolean is4x4 = dimension == DIMENSION_4X4;

zsonObject.put(“cardType2x2”, is2x2);

zsonObject.put(“cardType2x4”, is2x4);

zsonObject.put(“cardType4x4”, is4x4);

providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));

// 調(diào)用接口更新卡片數(shù)據(jù)

((MainAbility)context).loadData(formId,Constants.LOTTERY_ID_SSQ);

return providerFormInfo;

}

@Override

public void updateFormData(long formId, Object.。. vars) {

}

@Override

public void onTriggerFormEvent(long formId, String message) {

}

@Override

public Class《? extends AbilitySlice》 getRoutePageSlice(Intent intent) {

HiLog.info(TAG, “get the default page to route when you click card.”);

return null;

}

}

⑤簡(jiǎn)單的網(wǎng)絡(luò)優(yōu)化

由于 onCreateForm(Intent intent)方法會(huì)被調(diào)用多次,而每個(gè)類(lèi)型的卡片請(qǐng)求的數(shù)據(jù)一樣,聚合 api 一天 100 次免費(fèi)請(qǐng)求的次數(shù)一會(huì)兒就用完了,故對(duì)此進(jìn)行一個(gè)簡(jiǎn)單的優(yōu)化。

優(yōu)先看內(nèi)存緩存中是否有,有且為過(guò)期(緩存默認(rèn) 10 分鐘有效期)則直接返回,否則阻塞等待接口請(qǐng)求完成,對(duì)于并發(fā)請(qǐng)求,若請(qǐng)求隊(duì)列已有相同的請(qǐng)求,則阻塞,否則創(chuàng)建新的請(qǐng)求。

若不關(guān)心接口調(diào)用的可略過(guò)本節(jié):

// CachedLotteryDetailUtil.java/**

* CachedLotteryDetailUtil

* 緩存彩票詳情工具類(lèi),防止在卡片創(chuàng)建時(shí),重復(fù)調(diào)用接口

*

* @author:xwg

* @since 2021-07-30

*/public class CachedLotteryDetailUtil {

//緩存的有效時(shí)間 默認(rèn)10分鐘

private static final long CACHE_TIME = 10 * 60 * 1000;

// 緩存的彩票結(jié)果

private static volatile ConcurrentHashMap《String, LotteryBean》 cacheResMap = new ConcurrentHashMap《》();

//緩存的請(qǐng)求時(shí)間

private static volatile ConcurrentHashMap《String, Long》 reqTimeMap = new ConcurrentHashMap《》();

//正在請(qǐng)求 對(duì)應(yīng)的lotteryId

private static volatile List《String》 requestingLotteryId;

/**

* 獲取彩票詳情

*

* @param lotteryId

* @return

*/

public static Observable《LotteryBean》 getLotteryDetail(String lotteryId) {

if (cacheResMap.get(lotteryId) != null) {

if (!isExpired(lotteryId)) {

return Observable.create(emitter -》 {

if (!emitter.isDisposed()) {

emitter.onNext(cacheResMap.get(lotteryId));

}

});

} else {

cacheResMap.remove(lotteryId);

}

}

if (isRequesting(lotteryId)) {

return waitToRequestEnd(lotteryId);

} else {

return requestDetail(lotteryId);

}

}

/**

* 是否正在請(qǐng)求

*

* @param lotteryId

* @return

*/

private static boolean isRequesting(String lotteryId) {

if (requestingLotteryId == null || lotteryId.isEmpty()) {

return false;

}

return requestingLotteryId.contains(lotteryId);

}

/**

* 阻塞等待請(qǐng)求結(jié)果

*

* @param lotteryId

* @return

*/

private static Observable《LotteryBean》 waitToRequestEnd(final String lotteryId) {

return Observable.create(emitter -》 {

while (isRequesting(lotteryId)) {

try {

Thread.sleep(10);

} catch (InterruptedException e) {

}

}

if (!emitter.isDisposed()) {

try {

if (cacheResMap != null && cacheResMap.get(lotteryId) != null && !isExpired(lotteryId)) {

LotteryBean lotteryBean = cacheResMap.get(lotteryId);

emitter.onNext(lotteryBean);

if (!emitter.isDisposed()) {

emitter.onComplete();

}

} else {

Throwable throwable = new Throwable(“請(qǐng)求異常,請(qǐng)稍后再試”);

emitter.onError(throwable);

}

} catch (Exception e) {

emitter.onError(e);

}

}

});

}

/**

* 聯(lián)網(wǎng)請(qǐng)求彩票詳情

*

* @param lotteryId

* @return

*/

private static Observable《LotteryBean》 requestDetail(final String lotteryId) {

if (requestingLotteryId == null) {

requestingLotteryId = new LinkedList《》();

}

if (!lotteryId.isEmpty() && !requestingLotteryId.contains(lotteryId)) {

requestingLotteryId.add(lotteryId);

}

return Services.createAPI(LotteryAPI.class).queryDetail(lotteryId, “”, Constants.JH_KEY)

.doOnError(throwable -》 {

requestingLotteryId.remove(lotteryId);

reqTimeMap.remove(lotteryId);

})

.doAfterNext(lotteryBean -》 {

requestingLotteryId.remove(lotteryId);

cacheResMap.put(lotteryId, lotteryBean);

reqTimeMap.put(lotteryId, System.currentTimeMillis());

});

}

/**

* 緩存是否已經(jīng)過(guò)期

*

* @return

*/

private static boolean isExpired(String lotteryId) {

if (reqTimeMap == null || reqTimeMap.get(lotteryId) == null) {

return true;

}

return System.currentTimeMillis() - reqTimeMap.get(lotteryId) 》 CACHE_TIME;

}

}

⑥給卡片增加刷新事件和查看更多事件

給卡片的 index.json 文件添加 actions,定義 showMore 為 router 事件,觸發(fā)這個(gè)事件會(huì)跳轉(zhuǎn)到指定的 abilityName 對(duì)應(yīng)的 Ability。

updateData 為 message 事件,觸發(fā)該事件,會(huì)回調(diào) Ability 中的 onTriggerFormEvent(long formId, String message)方法。

// index.json

{

“data”: {

。..

},

“actions”: {

“showMore”: {

“action”: “router”,

“abilityName”: “com.xwg.lotteryquery.MainAbility”,

“params”: {

“message”: “fcsd”

}

},

“updateData”: {

“action”: “message”,

“params”: {

“key”: “fcsd”

}

}

}

}

卡片的布局文件中添加點(diǎn)擊事件:

《!--跳轉(zhuǎn)應(yīng)用首頁(yè)事件--》《text class=“text” style=“margin-left : 120px;” if=“{{ cardType2x4 || cardType4x4 }}” onclick=“showMore”》 查看更多

《/text》

《!--點(diǎn)擊刷新按鈕事件--》《image class=“refresh” src=“/common/refresh.png” onclick=“updateData”》《/image》

// SsqWidgetImpl.java@Overridepublic void onTriggerFormEvent(long formId, String message) {

HiLog.info(TAG, “======== ssq handle card click event.”);

((MainAbility)context).loadData(formId,Constants.LOTTERY_ID_SSQ);

}

添加定時(shí)刷新:打開(kāi) config.json,對(duì)于標(biāo)簽“scheduledUpdateTime”設(shè)定的時(shí)刻,當(dāng)?shù)竭_(dá)之后,MainAbility 中卡片的回調(diào)方法 onUpdateForm() 就會(huì)被自動(dòng)調(diào)用。

updateDuration 默認(rèn)為 1,下面配置表示:雙色球卡片允許定時(shí)刷新,從 10:30 開(kāi)始,每隔半小時(shí)刷新一次。

// config.json“forms”: [

{

“jsComponentName”: “ssq_widget”,

“isDefault”: true,

“scheduledUpdateTime”: “10:30”,

“defaultDimension”: “2*2”,

“name”: “SsqWidget”,

“description”: “雙色球”,

“colorMode”: “auto”,

“type”: “JS”,

“supportDimensions”: [

“2*2”,

“2*4”,

“4*4”

],

“updateEnabled”: true,

“updateDuration”: 1

}

。..

FormController 直接調(diào)用 MainAbility 的獲取數(shù)據(jù)方法:

// SsqWidgetImpl.java@Overridepublic void updateFormData(long formId, Object.。. vars) {

HiLog.info(TAG, “======== ssq update form data timing, default 30 minutes”);

((MainAbility)context).loadData(formId,Constants.LOTTERY_ID_SSQ);

}

⑦大樂(lè)透和福彩 3D 卡片的實(shí)現(xiàn)

這兩個(gè)卡片的實(shí)現(xiàn)過(guò)程和雙色球卡片基本一致,主要是 UI 上有些區(qū)別。大樂(lè)透卡片 4X4 樣式中,由于中獎(jiǎng)信息列表較長(zhǎng),引入了 list 和 list-item 組件,讓其可在卡片內(nèi)上下滾動(dòng),具體實(shí)現(xiàn)此處不再贅述,有興趣可閱讀源碼。

⑧歷史開(kāi)獎(jiǎng)列表的實(shí)現(xiàn)

這個(gè)界面也相對(duì)簡(jiǎn)單,使用了 swiper 組件,左右滑動(dòng)或點(diǎn)擊頭部標(biāo)簽欄,完成***、福彩 3D 標(biāo)簽頁(yè)的切換,每個(gè)標(biāo)簽頁(yè)展示對(duì)應(yīng)的近 50 期開(kāi)獎(jiǎng)結(jié)果,使用 list 和 list-item 組件渲染。

由于各列表 item 展示 UI 相近,故將其抽成了組件放置于 */common/component/lottery* 目錄下。

lottery 子組件部分,lottery.js:通過(guò) props 接收外部傳入的 lotteryData 數(shù)據(jù)。

// lottery.jsexport default {

props: {

lotteryData: {}

}

}

lottery.hml 組件布局代碼:

《!--lottery.hml--》《div class=“item”》

《div class=“item-header”》

《text style=“font-weight : bold;”》第{{ lotteryData.lottery_no }}期《/text》

《text class=“remarks”》開(kāi)獎(jiǎng)日期:{{ lotteryData.lottery_date }}《/text》

《/div》

《div style=“margin-left : 10px;”》

《text for=“{{ lotteryData.ballList }}”

class=“ball”

style=“background-color : {{ $idx 》= lotteryData.redBallCount ? ‘#6666FF’ : ‘#FF0033’ }};”

》{{ $item }}《/text》

《/div》

《div class=“amount-box”》

《div style=“flex-direction : column;”》

《text class=“text-small”》本期全國(guó)銷(xiāo)量《/text》

《text class=“text-amount”》{{ lotteryData.lottery_sale_amount }}《/text》

《/div》

《text class=“diver”》《/text》

《div style=“flex-direction : column;”》

《text class=“text-small”》累計(jì)獎(jiǎng)池《/text》

《text class=“text-amount”》{{ lotteryData.lottery_pool_amount || ‘0’ }}《/text》

《/div》

《/div》《/div》

css 比較簡(jiǎn)單,這里不再給出。

父組件實(shí)現(xiàn):

《!--home.hml--》《element name=‘lottery’ src=‘。./。./common/component/lottery/lottery.hml’》《/element》《div class=“container”》

《div class=“title-container”》

《text class=“title {{ currentIdx == 0 ? tabSelected : tabUnSelected }}” onclick=“onTabClick(0)”》雙色球《/text》

《text class=“title {{ currentIdx == 1 ? tabSelected : tabUnSelected }}” onclick=“onTabClick(1)”》大樂(lè)透《/text》

《text class=“title {{ currentIdx == 2 ? tabSelected : tabUnSelected }}” onclick=“onTabClick(2)”》福彩3D《/text》

《/div》

《swiper class=“swiper” id=“swiper” index=“0” indicator=“false” loop=“true”

digital=“false” on:change=“onChange”》

《div class=“swiperContent”》

《list class=“”》

《list-item for=“{{ ssqResList }}” class=“l(fā)ottery-item”》

《lottery lottery-data = “{{$item}}”》《/lottery》

《/list-item》

《/list》

《/div》

《div class=“swiperContent”》

《list class=“”》

《list-item for=“{{ dltResList }}” class=“l(fā)ottery-item”》

《lottery lottery-data = “{{$item}}”》《/lottery》

《/list-item》

《/list》

《/div》

《div class=“swiperContent”》

《list class=“”》

《list-item for=“{{ fcsdResList }}” class=“l(fā)ottery-item”》

《lottery lottery-data = “{{$item}}”》《/lottery》

《/list-item》

《/list》

《/div》

《/swiper》《/div》

《!--home.js--》

import http from ‘@ohos.net.http’;

const JH_URL = ‘http://apis.juhe.cn’const JH_KEY = ‘4931b786dd99c28e7e9990fb75c39fad’export default {

data: {

currentIdx: 0,

tabSelected: ‘tabSelected’,

tabUnSelected: ‘tabUnSelected’,

ssqResList: null, // 雙色球近期開(kāi)獎(jiǎng)結(jié)果列表

dltResList: null, // 大樂(lè)透近期開(kāi)獎(jiǎng)結(jié)果列表

fcsdResList: null, // 3D球近期開(kāi)獎(jiǎng)結(jié)果列表

},

onInit() {

this.querySsqHis();

this.queryDltHis();

this.queryFcsdHis();

},

// 查詢(xún)雙色球歷史開(kāi)獎(jiǎng)

querySsqHis() {

console.info(‘xwg== querySsqHis ----------’);

let _t = this

let httpRequest = http.createHttp();

let url = JH_URL + ‘/history’ + ‘?lottery_id=ssq&page_size=50&page=&key=’ + JH_KEY

httpRequest.request(url, (err, data) =》 {

if (err == null) {

let lotteryResList = JSON.parse(data.result).result.lotteryResList

_t.ssqResList = lotteryResList.map(item =》 {

item.ballList = item.lottery_res.split(“,”)

item.redBallCount = 6

return item

})

console.info(‘xwg== ssqResList:’ + JSON.stringify(_t.ssqResList));

} else {

console.info(‘xwg== error:’ + JSON.stringify(err));

}

});

},

// 查詢(xún)大樂(lè)透歷史開(kāi)獎(jiǎng)

queryDltHis() {

let _t = this

let httpRequest = http.createHttp();

let url = JH_URL + ‘/history’ + ‘?lottery_id=ssq&page_size=50&page=&key=’ + JH_KEY

httpRequest.request(url, (err, data) =》 {

if (err == null) {

let dltRes = JSON.parse(data.result).result.lotteryResList

_t.dltResList = dltRes.map(item =》 {

item.ballList = item.lottery_res.split(“,”)

item.redBallCount = 5

return item

})

} else {

console.info(‘xwg== error:’ + JSON.stringify(err));

}

});

},

// 查詢(xún)福彩3D歷史開(kāi)獎(jiǎng)

queryFcsdHis() {

let _t = this

let httpRequest = http.createHttp();

let url = JH_URL + ‘/history’ + ‘?lottery_id=ssq&page_size=50&page=&key=’ + JH_KEY

httpRequest.request(url, (err, data) =》 {

if (err == null) {

let fcsdRes = JSON.parse(data.result).result.lotteryResList

_t.fcsdResList = fcsdRes.map(item =》 {

item.ballList = item.lottery_res.split(“,”)

item.redBallCount = 3

return item

})

} else {

console.info(‘xwg== error:’ + JSON.stringify(err));

}

});

},

// swiper滑動(dòng)監(jiān)聽(tīng)

onChange(value) {

this.currentIdx = value.index

},

// tab click事件

onTabClick(idx) {

this.currentIdx = idx

this.$element(‘swiper’).swipeTo({

index: idx

});

},

computed: {}

}

尚未解決的問(wèn)題:這里引入了 http 組件進(jìn)行網(wǎng)絡(luò)請(qǐng)求,但在請(qǐng)求聚合接口時(shí),失敗率很高,但嘗試請(qǐng)求別的網(wǎng)站的 api 時(shí)沒(méi)有此現(xiàn)象,目前尚不知原因。

總結(jié)

由于這也是我第一次使用 JS UI 框架進(jìn)行卡片開(kāi)發(fā)的項(xiàng)目,水平有限,難免會(huì)對(duì)官方部分 API 理解不到位甚至理解有誤的地方,希望大家也多多指正,共同進(jìn)步。

這一路上雖然磕磕巴巴,也有很多吐槽,但我們從卡片 JS-UI API 5 到 API 6 功能上逐漸靠攏應(yīng)用 JS-UI 上也能看出來(lái)鴻蒙的努力,給它點(diǎn)時(shí)間,相信它功能上會(huì)變得更強(qiáng)大、完善;對(duì)于開(kāi)發(fā)也會(huì)變得更快捷、簡(jiǎn)單。

最后附上項(xiàng)目地址:lottery-query,請(qǐng)自行下載資源,歡迎交流學(xué)習(xí)。

https://gitee.com/chinasoft6_ohos/lottery-query

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2642

    瀏覽量

    68109
  • HarmonyOS
    +關(guān)注

    關(guān)注

    80

    文章

    2126

    瀏覽量

    33069

原文標(biāo)題:超實(shí)用!鴻蒙彩票查詢(xún)卡片

文章出處:【微信號(hào):gh_834c4b3d87fe,微信公眾號(hào):OpenHarmony技術(shù)社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    鴻蒙5開(kāi)發(fā)寶藏案例分享---多開(kāi)發(fā)實(shí)例(音樂(lè))

    關(guān)聯(lián)實(shí)際開(kāi)發(fā)中的高頻痛點(diǎn),比如內(nèi)存泄漏、跨端適配、服務(wù)卡片設(shè)計(jì)等。我整理了份超全解讀,帶你解鎖鴻蒙開(kāi)發(fā)的“隱藏Buff”! 、動(dòng)態(tài)布局實(shí)戰(zhàn):從折疊屏到多端適配 你以為的
    的頭像 發(fā)表于 06-30 11:54 ?344次閱讀

    鴻蒙開(kāi)發(fā)API9 到 API12,有哪些不同

    。 API9屬于“兼容安卓”時(shí)代的產(chǎn)物,和API10開(kāi)始的純血鴻蒙還是具有定區(qū)別的,當(dāng)然,雖然我們說(shuō)純血鴻蒙是從API10開(kāi)始的,但仍然以API12作為代表。從實(shí)際開(kāi)發(fā)角度來(lái)看,API12也屬于
    發(fā)表于 06-29 22:47

    FA模型卡片和Stage模型卡片切換

    卡片切換 卡片切換主要包含如下三部分: 卡片頁(yè)面布局:FA模型卡片和Stage模型卡片的布局都采用類(lèi)web范式開(kāi)發(fā)可以直接復(fù)用。
    發(fā)表于 06-06 08:10

    鴻蒙5開(kāi)發(fā)寶藏案例分享---多開(kāi)發(fā)實(shí)例(游戲)

    ?【開(kāi)發(fā)者必看】鴻蒙隱藏寶箱大公開(kāi)!這些實(shí)戰(zhàn)案例讓你的開(kāi)發(fā)效率翻倍! 哈嘍各位開(kāi)發(fā)者小伙伴!今天要和大家分享個(gè)讓我拍大腿的發(fā)現(xiàn)——原來(lái)鴻蒙官方早就給我們準(zhǔn)備了超多高質(zhì)量開(kāi)發(fā)案例!(就
    發(fā)表于 06-03 18:22

    鴻蒙5開(kāi)發(fā)寶藏案例分享---多開(kāi)發(fā)實(shí)例(地圖導(dǎo)航)

    ? 鴻蒙開(kāi)發(fā)隱藏寶藏大公開(kāi)!手把手教你玩轉(zhuǎn)\"多\"地圖導(dǎo)航案例 ? 大家好呀!我是你們的老朋友,今天要給大家扒鴻蒙官方文檔里那些\"藏得深\"的實(shí)戰(zhàn)
    發(fā)表于 06-03 16:17

    效率大升!AI賦能鴻蒙萬(wàn)能卡片開(kāi)發(fā)

    萬(wàn)能卡片,作為鴻蒙生態(tài)應(yīng)用和元服務(wù)的重要展示形式,憑借將關(guān)鍵信息和核心操作前置,實(shí)現(xiàn)服務(wù)直達(dá)、減少跳轉(zhuǎn)層級(jí)的體驗(yàn)效果,備受用戶(hù)和開(kāi)發(fā)者青睞。但傳統(tǒng)卡片的設(shè)計(jì)和編碼流程相對(duì)繁瑣,影響了萬(wàn)能卡片
    的頭像 發(fā)表于 01-13 13:44 ?792次閱讀
    效率大升!AI賦能<b class='flag-5'>鴻蒙</b>萬(wàn)能<b class='flag-5'>卡片</b>開(kāi)發(fā)

    OpenHarmony源碼編譯后燒錄鏡像教程,RK3566鴻蒙開(kāi)發(fā)板演示

    本文介紹瑞芯微主板/開(kāi)發(fā)板編譯OpenHarmony源碼后燒錄鏡像的教程,觸覺(jué)智能Purple Pi OH鴻蒙開(kāi)發(fā)板演示。搭載了瑞芯微RK3566四核處理器,樹(shù)莓派卡片電腦設(shè)計(jì),支持開(kāi)源鴻蒙OpenHarmony3.2-5.0
    的頭像 發(fā)表于 12-30 10:08 ?834次閱讀
    OpenHarmony源碼編譯后燒錄鏡像教程,RK3566<b class='flag-5'>鴻蒙</b>開(kāi)發(fā)板演示

    鴻蒙原生開(kāi)發(fā)手記:04-個(gè)完整元服務(wù)案例

    /main_pages.json 中配置,路由名與文件名一一對(duì)應(yīng)。 在 main_pages.json 所在地目錄中,可以看到個(gè) form_config.json文件,這個(gè)用來(lái)配置服務(wù)卡片,在此按下不表。 頁(yè)面中多
    發(fā)表于 12-27 10:35

    何在開(kāi)源鴻蒙OpenHarmony開(kāi)啟SELinux模式?RK3566鴻蒙開(kāi)發(fā)板演示

    本文介紹開(kāi)源鴻蒙OpenHarmony系統(tǒng)下,開(kāi)啟/關(guān)閉SELinux權(quán)限的方法,觸覺(jué)智能Purple Pi OH鴻蒙開(kāi)發(fā)板演示,已適配全新OpenHarmony5.0 Release系統(tǒng)
    的頭像 發(fā)表于 11-18 19:03 ?844次閱讀
    如<b class='flag-5'>何在</b>開(kāi)源<b class='flag-5'>鴻蒙</b>OpenHarmony開(kāi)啟SELinux模式?RK3566<b class='flag-5'>鴻蒙</b>開(kāi)發(fā)板演示

    鴻蒙原生開(kāi)發(fā)手記:02-服務(wù)卡片開(kāi)發(fā)

    介紹 服務(wù)卡片直桌面小組件,可以放置在桌面上等位置,觸即達(dá)。 服務(wù)卡片分為靜態(tài)卡片和動(dòng)態(tài)卡片
    發(fā)表于 11-14 17:48

    鴻蒙原生開(kāi)發(fā)手記:01-元服務(wù)開(kāi)發(fā)

    簡(jiǎn)介 元服務(wù)是鴻蒙中的種輕量應(yīng)用形態(tài),無(wú)需下載,直接運(yùn)行。類(lèi)似于微信小程序,但與小程序不同的是,元服務(wù)更加輕量。 元服務(wù)使用原生開(kāi)發(fā),是系統(tǒng)級(jí)提供的,無(wú)論從易用性、性能、體驗(yàn)上,都要比小程序好
    發(fā)表于 11-14 17:28

    鴻蒙系統(tǒng)專(zhuān)用版微信內(nèi)測(cè)即將啟動(dòng)

    Next系統(tǒng)的用戶(hù)參與內(nèi)測(cè)活動(dòng),以進(jìn)步優(yōu)化微信在鴻蒙系統(tǒng)上的表現(xiàn)。內(nèi)測(cè)活動(dòng)將為廣大用戶(hù)提供個(gè)
    的頭像 發(fā)表于 11-07 10:58 ?1505次閱讀

    原生鴻蒙操作系統(tǒng)正式發(fā)布,誠(chéng)邁科技與華為起共建鴻蒙新世界

    特性等提升顯著,標(biāo)志著我國(guó)在操作系統(tǒng)研發(fā)領(lǐng)域取得了重大突破。 誠(chéng)邁科技與華為直保持著緊密的伙伴關(guān)系,公司不僅是最早加入鴻蒙生態(tài)的共建者之,也是
    的頭像 發(fā)表于 10-28 09:29 ?1439次閱讀
    原生<b class='flag-5'>鴻蒙</b>操作<b class='flag-5'>系統(tǒng)</b>正式發(fā)布,誠(chéng)邁科技與華為<b class='flag-5'>一</b>起共建<b class='flag-5'>鴻蒙</b>新世界

    基于鴻蒙Next模擬卡片數(shù)據(jù)數(shù)據(jù)更新

    、介紹 基于鴻蒙Next模擬卡片數(shù)據(jù)數(shù)據(jù)更新二、場(chǎng)景需求 電商平臺(tái)產(chǎn)品信息更新、 客戶(hù)關(guān)系管理(CRM)系統(tǒng)、 社交媒體用戶(hù)資料更新、 健康管理
    發(fā)表于 08-30 15:32

    國(guó)產(chǎn)KylinOS銀河麒麟系統(tǒng)適配OBOO鷗柏觸摸屏查詢(xún)體機(jī)完成調(diào)試

    觸摸屏麒麟系統(tǒng)界面“OBOO鷗柏”品牌部分商用液晶顯示產(chǎn)品已接入國(guó)產(chǎn)麒麟系統(tǒng)AI人工智能,銀河麒麟(KylinOS),并上架京東商城,液晶廣告機(jī),觸摸屏查詢(xún)體機(jī),交互式
    的頭像 發(fā)表于 08-23 18:03 ?1681次閱讀
    國(guó)產(chǎn)KylinOS銀河麒麟<b class='flag-5'>系統(tǒng)</b>適配OBOO鷗柏觸摸屏<b class='flag-5'>查詢(xún)</b><b class='flag-5'>一</b>體機(jī)完成調(diào)試