色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何在鴻蒙系統弄一個彩票查詢卡片

OpenHarmony技術社區 ? 來源:HarmonyOS技術社區 ? 作者:中軟國際 ? 2021-09-06 09:17 ? 次閱讀

接觸鴻蒙開發已經有 3 個來月了,最近開始在看鴻蒙卡片開發。因為之前的開發大都是基于 Java UI,但按官方的說法,JS 卡片相比 Java 卡片有更大的優勢,故決定寫個 JS 卡片的 demo 來練練手。

碰巧,前幾天和媳婦兒在散步時撿到 1 元錢,沒能交給警察叔叔,媳婦兒就提議“我們把它昧了吧,買張彩票。”

由于不是老 CM,沒有關注開獎的習慣,想著要是能把開獎結果放在手機桌面顯示就好了,這樣就不會錯過我一夜暴富的機會了。有了需求就開擼,然后就有了這篇文章!

項目簡介

①本項目基于 API 6 開發,demo 運行在 API 6 以下的手機上會出現部分功能不能使用的現象。

②卡片功能上實現了***、福彩 3D 的最近一期開獎結果查詢,點擊卡片“刷新”按鈕,調用接口更新最新數據;點擊“查看更多”按鈕,跳轉至應用主界面。

③應用主界面上實現了***、福彩 3D 近 50 期開獎結果查看。

④以上數據均使用了聚合數據的 https://www.juhe.cn/docs/api/id/300 免費接口。

需申請 key,一個 key 一天可免費調用 100 次,如遇 key使 用次數過多導致接口請求失敗情況時,開發者可自行申請 key 并替換 Constants.java 文件下的 JH_KEY 常量值),數據可能會有延遲。

⑤卡片開發部分使用了卡片的 JS UI 框架,但由于系統 PA 與 FA 相互調用的限制問題,卡片的業務邏輯部分仍然采用 Java 代碼編寫。

PS:最開始的想法是盡量可能的少依賴 Java 代碼,故嘗試了 JS FA 與 Java PA 相互調用的方式,但當應用進程被干掉時,Java 端無法再調用到 JS 端方法。

這樣就導致 JS 只能寫 UI 部分,業務邏輯還得 Java 層實現。有知道解決辦法的也麻煩告知一聲。

⑥卡片業務層使用 Java 開發,采用了簡單的 MVP 架構,網絡請求和數據處理部分使用了 rxjava3+retrofit 框架。

⑦應用主界面使用了 JS-UI 框架實現。

實現效果

請忽略我粗陋的 UI 設計和 GIF 的渣渣像素。

項目代碼結構分析

base:

IBasePresenter:MVP 架構中 presenter 基類接口

IBaseView:MVP 架構中 view 基類接口

network:

bean,LotteryBean:彩票詳情接口返回對應 model

CachedLotteryDetailUtil:彩票詳情接口請求工具類,主要作用是防止重復調用詳情接口

LogInterceptor:OKhttp 日志攔截工具類

LotteryAPI:接口請求類,通過 retrofit 注解,將接口返回數據轉化為實體類

Services:配置 Retrofit 并提供

presenter:

IMainContract:MVP 中 view 與 presenter 的橋梁

MainPresenter:提供彩票詳情接口的請求,并處理接口返回數據為卡片需要的 ZSONObject 對象

utils:

LogUtil:日志打印工具類

widget:

controller:FormController:創建卡片時自動生成,卡片管理器的抽象基類;FormControllerManager:創建卡片時自動生成,管理各個 FormController 的工具類

dltwidget.DltWidgetImpl:大樂透卡片管理類,提供了創建卡片、更新卡片、刪除卡片、卡片點擊事件等行為的回調方法

fcsdwidget.FcsdWidgetImpl:福彩 3D 卡片管理類,提供了創建卡片、更新卡片、刪除卡片、卡片點擊事件等行為的回調方法

ssqwidget.SsqWidgetImpl:雙色球卡片管理類,提供了創建卡片、更新卡片、刪除卡片、卡片點擊事件等行為的回調方法

Constants:常量工具類。

MainAbility:HAP 的入口 ability,由 DevEco Studio 自動生成。同時也是各個卡片對應的 Ability,用來項各個 FormController 分發事件。

default:

common,component/lottery:應用首頁列表 item 組件;images :資源圖片

pages,home:應用首頁

dlt_widget:

common:資源圖片存放目錄

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

fcsd_widget:目錄結構同 dlt_widget。

ssq_widget:目錄結構同 dlt_widget。

詳細實現過程

①創建雙色球卡片

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

在模板選擇界面,選擇基本的模板 Grid Pattern,點擊按鈕 Next,進入到卡片配置界面:

首先配置卡片的名稱和描述;然后配置卡片關聯的 Page Ability;然后配置卡片的編程語言類型是 JS;接下來配置卡片的 JS 組件名稱;最后配置卡片支持的規格,勾選支持 2x4、4x4 規格。

重復上述步驟,創建出大樂透和雙色球卡片。運行項目,長按圖標打開卡片管理界面,我們能看到剛創建的 3 類卡片,且每類卡片對應 3 種不同樣式,如下圖所示:

②繪制雙色球卡片 UI

我們編寫雙色球界面:

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

《div》

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

《text class=“text-small” style=“margin-left : 15px;” if=“{{ cardType2x4 || cardType4x4 }}”》每周二、四、日開獎《/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 }}”》 開獎日期:《/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”》本期全國銷量《/text》

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

《/div》

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

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

《text class=“text-small”》累計獎池《/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”》獎項《/text》

《text class=“text-prize”》中獎條件《/text》

《text class=“text-prize”》中獎注數《/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 }}”》更新時間:《/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,

“lotteryData”: {

“lottery_no”: “21081”,

“lottery_date”: “2021-07-20”,

“lottery_sale_amount”:“344,437,194”,

“lottery_pool_amount”:“997,378,346”

},

“lotteryRed”:[“01”,“03”,“05”,“18”,“22”,“23”],

“lotteryBlue”:[“01”],

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

“lottery_prize”:[

{

“prize_name”:“一等獎”,

“prize_num”:“4”,

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

“prize_require”:“6+1”

},

{

“prize_name”:“二等獎”,

“prize_num”:“135”,

“prize_amount”:“207,725”,

“prize_require”:“6+0”

},

{

“prize_name”:“三等獎”,

“prize_num”:“879”,

“prize_amount”:“3,000”,

“prize_require”:“5+1”

},

{

“prize_name”:“四等獎”,

“prize_num”:“45659”,

“prize_amount”:“200”,

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

},

{

“prize_name”:“五等獎”,

“prize_num”:“1001881”,

“prize_amount”:“10”,

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

},

{

“prize_name”:“六等獎”,

“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;

}

編寫完成后,重新運行,不出意外你應該能看到如下效果:

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

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

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

不同于應用開發中的 JS UI 框架,這里的條件渲染不支持表達式。

css 不支持標簽選擇器。

部分 css 樣式不能被繼承,例如給父 div 元素設置了 font-size,你會發現 div 中的 text 組件并沒繼承上述樣式。

列表渲染的 for 循環的數組必須是 index.json data 對象的最外層。

不支持雙層 for 循環。

api6 不兼容 api5 的設備。

你會發現卡片 JSON 文件中的 data 對象數據結構同接口返回的數據結構有些差異,就是因為上述原因導致的。

③獲取網絡數據

簡單的 MVP 架構,采用 Retrofit+RxJava 作為異步網絡請求框架。

build.gradle 中添加 RxJava 和 Retrofit 的依賴:

// 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 文件中添加網絡權限:

// 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”

}

],

。..

}

創建接口請求:

// LotteryAPI.javapublic interface LotteryAPI {

@POST(“/lottery/query”)

@FormUrlEncoded

Observable《LotteryBean》 queryDetail(@Field(“lottery_id”) String lottery_id, @Field(“lottery_no”) String lottery_no, @Field(“key”) String key);

}

P 層和 V 層的接口比較簡單,不在羅列。編寫 P 層業務邏輯:

//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() {

}

});

}

/**

* 根據接口返回的數據,組裝成JS卡片需要的數據

*

* @param result

* @return

*/private ZSONObject buildDataByResult(LotteryBean result) {

LotteryBean.DetailBean detailBean = result.getResult();

ZSONObject data = new ZSONObject();

ZSONObject lotteryData = new ZSONObject();

lotteryData.put(“lottery_no”, detailBean.getLottery_no());

lotteryData.put(“lottery_date”, detailBean.getLottery_date());

lotteryData.put(“lottery_sale_amount”, detailBean.getLottery_sale_amount());

lotteryData.put(“lottery_pool_amount”, detailBean.getLottery_pool_amount());

data.put(“lotteryData”, lotteryData);

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

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

data.put(“lotteryRed”, Arrays.copyOfRange(ballArray, 0, 6));

data.put(“lotteryBlue”, Arrays.copyOfRange(ballArray, 6, 7));

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

data.put(“lotteryRed”, Arrays.copyOfRange(ballArray, 0, 5));

data.put(“lotteryBlue”, Arrays.copyOfRange(ballArray, 5, 7));

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

data.put(“lotteryRed”, 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(“lottery_prize”, zsonArray);

return data;

}

④V 層調用 P 層,更新卡片

這里提下 MainAbility 的 onCreateForm 方法,它在進入卡片管理界面時被調用,內部通過 FormControllerManager 獲取了卡片對應的 FormController,并調用了其 bindFormData() 方法。

由于我們卡片展示的數據來源于網絡請求,在對應的 FormController 實現類中不太好獲得 formId,所以我們稍微改造一下 FormController 的 bindFormData 方法,把 formId 給傳進去。

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;

}

/**

* 查詢彩票開獎詳情

*

* @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));

// 調用接口更新卡片數據

((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;

}

}

⑤簡單的網絡優化

由于 onCreateForm(Intent intent)方法會被調用多次,而每個類型的卡片請求的數據一樣,聚合 api 一天 100 次免費請求的次數一會兒就用完了,故對此進行一個簡單的優化。

優先看內存緩存中是否有,有且為過期(緩存默認 10 分鐘有效期)則直接返回,否則阻塞等待接口請求完成,對于并發請求,若請求隊列已有相同的請求,則阻塞,否則創建新的請求。

若不關心接口調用的可略過本節:

// CachedLotteryDetailUtil.java/**

* CachedLotteryDetailUtil

* 緩存彩票詳情工具類,防止在卡片創建時,重復調用接口

*

* @author:xwg

* @since 2021-07-30

*/public class CachedLotteryDetailUtil {

//緩存的有效時間 默認10分鐘

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

// 緩存的彩票結果

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

//緩存的請求時間

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

//正在請求 對應的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);

}

}

/**

* 是否正在請求

*

* @param lotteryId

* @return

*/

private static boolean isRequesting(String lotteryId) {

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

return false;

}

return requestingLotteryId.contains(lotteryId);

}

/**

* 阻塞等待請求結果

*

* @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(“請求異常,請稍后再試”);

emitter.onError(throwable);

}

} catch (Exception e) {

emitter.onError(e);

}

}

});

}

/**

* 聯網請求彩票詳情

*

* @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());

});

}

/**

* 緩存是否已經過期

*

* @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 事件,觸發這個事件會跳轉到指定的 abilityName 對應的 Ability。

updateData 為 message 事件,觸發該事件,會回調 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”

}

}

}

}

卡片的布局文件中添加點擊事件:

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

《/text》

《!--點擊刷新按鈕事件--》《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);

}

添加定時刷新:打開 config.json,對于標簽“scheduledUpdateTime”設定的時刻,當到達之后,MainAbility 中卡片的回調方法 onUpdateForm() 就會被自動調用。

updateDuration 默認為 1,下面配置表示:雙色球卡片允許定時刷新,從 10:30 開始,每隔半小時刷新一次。

// 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 直接調用 MainAbility 的獲取數據方法:

// 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);

}

⑦大樂透和福彩 3D 卡片的實現

這兩個卡片的實現過程和雙色球卡片基本一致,主要是 UI 上有些區別。大樂透卡片 4X4 樣式中,由于中獎信息列表較長,引入了 list 和 list-item 組件,讓其可在卡片內上下滾動,具體實現此處不再贅述,有興趣可閱讀源碼。

⑧歷史開獎列表的實現

這個界面也相對簡單,使用了 swiper 組件,左右滑動或點擊頭部標簽欄,完成***、福彩 3D 標簽頁的切換,每個標簽頁展示對應的近 50 期開獎結果,使用 list 和 list-item 組件渲染。

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

lottery 子組件部分,lottery.js:通過 props 接收外部傳入的 lotteryData 數據。

// 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”》開獎日期:{{ 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”》本期全國銷量《/text》

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

《/div》

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

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

《text class=“text-small”》累計獎池《/text》

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

《/div》

《/div》《/div》

css 比較簡單,這里不再給出。

父組件實現:

《!--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)”》大樂透《/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=“lottery-item”》

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

《/list-item》

《/list》

《/div》

《div class=“swiperContent”》

《list class=“”》

《list-item for=“{{ dltResList }}” class=“lottery-item”》

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

《/list-item》

《/list》

《/div》

《div class=“swiperContent”》

《list class=“”》

《list-item for=“{{ fcsdResList }}” class=“lottery-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, // 雙色球近期開獎結果列表

dltResList: null, // 大樂透近期開獎結果列表

fcsdResList: null, // 3D球近期開獎結果列表

},

onInit() {

this.querySsqHis();

this.queryDltHis();

this.queryFcsdHis();

},

// 查詢雙色球歷史開獎

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));

}

});

},

// 查詢大樂透歷史開獎

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));

}

});

},

// 查詢福彩3D歷史開獎

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滑動監聽

onChange(value) {

this.currentIdx = value.index

},

// tab click事件

onTabClick(idx) {

this.currentIdx = idx

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

index: idx

});

},

computed: {}

}

尚未解決的問題:這里引入了 http 組件進行網絡請求,但在請求聚合接口時,失敗率很高,但嘗試請求別的網站的 api 時沒有此現象,目前尚不知原因。

總結

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

這一路上雖然磕磕巴巴,也有很多吐槽,但我們從卡片 JS-UI API 5 到 API 6 功能上逐漸靠攏應用 JS-UI 上也能看出來鴻蒙的努力,給它點時間,相信它功能上會變得更強大、完善;對于開發也會變得更快捷、簡單。

最后附上項目地址:lottery-query,請自行下載資源,歡迎交流學習。

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

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2634

    瀏覽量

    66309
  • HarmonyOS
    +關注

    關注

    79

    文章

    1974

    瀏覽量

    30149

原文標題:超實用!鴻蒙彩票查詢卡片

文章出處:【微信號:gh_834c4b3d87fe,微信公眾號:OpenHarmony技術社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    鴻蒙原生開發手記:02-服務卡片開發

    介紹 服務卡片直桌面小組件,可以放置在桌面上等位置,觸即達。 服務卡片分為靜態卡片和動態卡片
    發表于 11-14 17:48

    鴻蒙原生開發手記:01-元服務開發

    簡介 元服務是鴻蒙中的種輕量應用形態,無需下載,直接運行。類似于微信小程序,但與小程序不同的是,元服務更加輕量。 元服務使用原生開發,是系統級提供的,無論從易用性、性能、體驗上,都要比小程序好
    發表于 11-14 17:28

    基于鴻蒙Next模擬卡片數據數據更新

    、介紹 基于鴻蒙Next模擬卡片數據數據更新二、場景需求 電商平臺產品信息更新、 客戶關系管理(CRM)系統、 社交媒體用戶資料更新、 健康管理
    發表于 08-30 15:32

    AIGC系統中聊天小助手卡片小組件嵌套設計實踐

    1.項目描述 領航者卡片樣式較多,有些卡片比較近似;可以用嵌套方案,實現卡片,多個子單元 可拔插組件式
    的頭像 發表于 06-12 11:20 ?812次閱讀
    AIGC<b class='flag-5'>系統</b>中聊天小助手<b class='flag-5'>卡片</b>小組件嵌套設計實踐

    鴻蒙開發接口Ability框架:【@ohos.application.formInfo (FormInfo)】

    FormInfo模塊提供對卡片的相關卡片信息和狀態進行設置和查詢的能力。
    的頭像 發表于 05-08 09:49 ?500次閱讀
    <b class='flag-5'>鴻蒙</b>開發接口Ability框架:【@ohos.application.formInfo (FormInfo)】

    OpenHarmony開發案例:【電影卡片

    基于元服務卡片的能力,實現帶有卡片的電影應用,介紹卡片的開發過程和生命周期實現。
    的頭像 發表于 04-15 17:53 ?1262次閱讀
    OpenHarmony開發案例:【電影<b class='flag-5'>卡片</b>】

    鴻蒙OS開發學習:【尺寸適配實現】

    鴻蒙開發中,尺寸適配是重要的概念,它可以幫助我們在不同屏幕尺寸的設備上正確顯示和布局我們的應用程序。本文將介紹如何在鴻蒙開發中實現尺寸
    的頭像 發表于 04-10 16:05 ?1735次閱讀
    <b class='flag-5'>鴻蒙</b>OS開發學習:【尺寸適配實現】

    鴻蒙OS開發案例:【Stage模型卡片

    本示例展示了Stage模型卡片提供方的創建與使用。
    的頭像 發表于 04-09 17:13 ?987次閱讀
    <b class='flag-5'>鴻蒙</b>OS開發案例:【Stage模型<b class='flag-5'>卡片</b>】

    鴻蒙OS實戰開發:【多設備自適應服務卡片

    服務卡片的布局和使用,其中卡片內容顯示使用了次開發,多端部署的能力實現多設備自適應。 用到了卡片擴展模塊接口,[@ohos.app.form.FormExtensionAbil
    的頭像 發表于 04-09 09:20 ?857次閱讀
    <b class='flag-5'>鴻蒙</b>OS實戰開發:【多設備自適應服務<b class='flag-5'>卡片</b>】

    鴻蒙OS開發實例:【手擼服務卡片

    服務卡片指導文檔位于“**開發/應用模型/Stage模型開發指導/Stage模型應用組件**”路徑下,說明其極其重要。本篇文章將分享實現服務卡片的過程和代碼
    的頭像 發表于 03-28 22:11 ?1191次閱讀
    <b class='flag-5'>鴻蒙</b>OS開發實例:【手擼服務<b class='flag-5'>卡片</b>】

    何在stm32cubemx中精確查詢

    stm32cubemx中finder功能的確很方便,但我遇到問題 現在片子上pin復用功能越來越多,越來越方便 我同時需要多個接口,如,1can,2spi,1
    發表于 03-12 06:11

    鴻蒙】桌面卡片開發教程:從底層原理開始講透call事件的刷新機制 “堅果派-咸魚”

    為什么桌面卡片需要使用特殊機制來刷新? 主要有兩原因:第是 OpenHarmonyOS Api9 的桌面卡片出于降低系統能耗的目的,被限
    的頭像 發表于 03-04 10:02 ?714次閱讀
    【<b class='flag-5'>鴻蒙</b>】桌面<b class='flag-5'>卡片</b>開發教程:從底層原理開始講透call事件的刷新機制 “堅果派-咸魚”

    emui10怎么升級鴻蒙系統

    鴻蒙系統是華為開發的新代操作系統,而EMUI 10則是基于Android的用戶界面。目前,華為尚未公開說明如何在EMUI 10設備上升級到
    的頭像 發表于 02-02 11:31 ?2397次閱讀

    何在鴻蒙系統上安裝Google Play

    隨著鴻蒙(HarmonyOS)系統的逐漸普及和用戶基數的增加,些用戶希望能在鴻蒙系統上使用Google Play商店以獲取更多應用。然而,
    的頭像 發表于 01-31 17:13 ?1.6w次閱讀

    【年度精選】2023年度top5榜單——鴻蒙開發經驗

    的應用。通過學習本教程,你將了解開源鴻蒙系統在不同場景下的應用和實踐,激發你對人工智能和開源鴻蒙系統的興趣和創造力。 2、開發
    發表于 01-10 17:19
    主站蜘蛛池模板: 日韩精品免费一区二区| 最近的2019中文字幕国语完整版 | 日韩黄色软件| 久久不射电影网| 高干紧射H后入| 最近中文字幕免费高清MV视频6| 涩涩视频下载| 免费一级特黄欧美大片久久网| 国产女人91精品嗷嗷嗷嗷| 99久久爱re热6在线播放| 亚洲 欧美 中文字幕 在线| 奇米精品一区二区三区在线观看| 国产在线观看免费观看| 大学生第一次破苞疼哭了| 最近日本免费观看MV免费| 亚洲国产中文在线视频免费| 欧美同志高清vivoeso| 狼群资源网中文字幕| 花蝴蝶高清观看免费| 国产精品JK白丝AV网站| 啊片色播电影| 99久久国产综合色| 总攻催眠受的高h巨肉np| 亚洲日产2020乱码草莓毕| 偷尝禁果H1V1幸运的山熊| 人妻少妇偷人精品无码洋洋AV| 看全色黄大色大片免费久黄久| 好大好硬好爽好深好硬视频| 国产99RE在线观看69热| 草莓在线观看| av av在线| AV天堂午夜精品蜜臀AV| 91精品在线国产| 24小时日本在线观看片免费| 诱咪youmiss| 伊人角狠狠狠狠| 一个人免费观看完整视频日本| 亚洲精品一二三区-久久| 亚洲 欧美 国产 综合 播放| 天天躁夜夜踩很很踩2022| 色列少女漫画|