wangliang_wd

Merge branch 'main' of http://192.168.1.42/developOne/harmonyPool into main

* 'main' of http://192.168.1.42/developOne/harmonyPool:
  降级map api等级
  权限申请暂时注释掉
  增加logger日志开关
  增加权限申请工具类
  fix:电子报文字版列表,点击跳转详情事件添加
  app启动增加协议网络获取
  版面切换
  人民号顶导切换
  首页头部样式优化
  底导切换修复
  fix:隐藏卡片和创作者,隐藏搜索状态导航
  desc:4.0  搜索默认滚动
  desc:退出登录接口调试、RSA加密调试
  首页频道缓存
  播报推荐列表弹窗添加
  desc:首页搜索 滚动
Showing 37 changed files with 874 additions and 155 deletions
{
"code": "0",
"data": [
"习语",
"党史学习",
"高考倒计时"
],
"message": "Success",
"success": true,
"timestamp": 1712562841885
}
\ No newline at end of file
... ...
... ... @@ -5,6 +5,7 @@ import { BottomNavDTO } from '../../repository/bean/BottomNavDTO';
import { UIUtils } from '../../repository/UIUtils';
import { MinePageComponent } from './MinePageComponent';
import PageViewModel from '../../viewmodel/PageViewModel';
import { FirstTabTopComponent } from './FirstTabTopComponent';
const TAG = 'BottomNavigationComponent';
... ... @@ -51,6 +52,9 @@ export struct BottomNavigationComponent {
// 我的页面组件数据列表
MinePageComponent()
} else {
if(index === 0 ){
FirstTabTopComponent()
}
TopNavigationComponent({ topNavList: navItem.topNavChannelList })
}
}
... ...
import SearcherAboutDataModel from '../../model/SearcherAboutDataModel'
/**
* 首页顶部搜索导航栏
* 竖向滚动实现方案
* 方案一 使用动画 + 定时器
* 方案二 使用容器组件Swiper(当前)
*/
const TAG = "FirstTabTopComponent"
@Component
export struct FirstTabTopComponent{
@State searchTextData :string[] = []
private swiperController: SwiperController = new SwiperController()
aboutToAppear(){
this.getSearchHint()
}
getSearchHint(){
SearcherAboutDataModel.getSearchHintData(getContext(this)).then((value)=>{
if(value!=null){
this.searchTextData = value
}
}).catch((err:Error)=>{
console.log(TAG,JSON.stringify(err))
})
}
build(){
Column(){
Row(){
Row(){
Image($r('app.media.search_icon'))
.objectFit(ImageFit.Cover)
.height('23lpx')
.width('23lpx')
.margin({right:'13lpx'})
.interpolation(ImageInterpolation.Medium)
if(this.searchTextData!=null && this.searchTextData.length>0){
Swiper(this.swiperController) {
ForEach(this.searchTextData, (item: string, index: number ) => {
Text(item)
.fontWeight('400lpx')
.fontSize('25lpx')
.fontColor($r('app.color.color_666666'))
.lineHeight('35lpx')
.textAlign(TextAlign.Start)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Clip})
})
}
.loop(true)
.autoPlay(true)
.interval(3000)
.indicator(false)
.vertical(true)
}
}.width('257lpx')
.height('61lpx')
.padding({left:'31lpx'})
.backgroundImage($r('app.media.top_search_bg'))
.backgroundImageSize(ImageSize.Cover)
.alignItems(VerticalAlign.Center)
Image($r('app.media.top_title_bg'))
.objectFit(ImageFit.Auto)
.height('58lpx')
.width('152lpx')
.interpolation(ImageInterpolation.Medium)
Row(){
Text("早晚报")
}.backgroundImage($r('app.media.top_right_bg'))
.justifyContent(FlexAlign.Center)
.backgroundImageSize(ImageSize.Cover)
.width('257lpx')
.height('61lpx')
}.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}.height('73lpx')
.width('100%')
.justifyContent(FlexAlign.End)
.backgroundColor($r('app.color.white'))
}
}
\ No newline at end of file
... ...
... ... @@ -62,13 +62,15 @@ export struct MinePageComponent {
//Grid 区域
MinePagePersonFunctionUI({personalData:$personalData})
//Card
MinePageCardUI()
// MinePageCardUI()
//创作者区域
MinePageCreatorFunctionUI({creatorData:$creatorData})
// MinePageCreatorFunctionUI({creatorData:$creatorData})
//更多功能
MinePageMoreFunctionUI({moreData:$moreData})
}.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
}
@Styles setFullWidthAndHeight(){
... ...
import { Logger, ResourcesUtils } from 'wdKit';
import { ResponseDTO, WDHttp } from 'wdNetwork';
import HashMap from '@ohos.util.HashMap';
import { HttpUrlUtils } from '../network/HttpUrlUtils';
const TAG = "SearcherAboutDataModel"
/**
* 我的页面 所有数据 获取封装类
*/
class SearcherAboutDataModel{
private static instance: SearcherAboutDataModel;
private constructor() { }
/**
* 单例模式
* @returns
*/
public static getInstance(): SearcherAboutDataModel {
if (!SearcherAboutDataModel.instance) {
SearcherAboutDataModel.instance = new SearcherAboutDataModel();
}
return SearcherAboutDataModel.instance;
}
/**
* 首页 搜索提示滚动内容
*/
getSearchHintData(context: Context): Promise<string[]> {
return new Promise<string[]>((success, error) => {
Logger.info(TAG, `getSearchHintData start`);
this.fetchSearchHintData().then((navResDTO: ResponseDTO<string[]>) => {
if (!navResDTO || navResDTO.code != 0) {
success(this.getSearchHintDataLocal(context))
return
}
Logger.info(TAG, "getSearchHintData then,SearchHintDataResDTO.timeStamp:" + navResDTO.timestamp);
let navigationBean = navResDTO.data as string[]
success(navigationBean);
}).catch((err: Error) => {
Logger.error(TAG, `fetchSearchHintData catch, error.name : ${err.name}, error.message:${err.message}`);
success(this.getSearchHintDataLocal(context))
})
})
}
fetchSearchHintData() {
let url = HttpUrlUtils.getSearchHintDataUrl()
let headers: HashMap<string, string> = HttpUrlUtils.getYcgCommonHeaders();
return WDHttp.get<ResponseDTO<string[]>>(url, headers)
};
async getSearchHintDataLocal(context: Context): Promise<string[]> {
Logger.info(TAG, `getSearchHintDataLocal start`);
let compRes: ResponseDTO<string[]> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<string[]>>('search_hint_data.json' ,context);
if (!compRes || !compRes.data) {
Logger.info(TAG, `getSearchHintDataLocal compRes is empty`);
return []
}
Logger.info(TAG, `getSearchHintDataLocal compRes : ${JSON.stringify(compRes)}`);
return compRes.data
}
}
const searcherAboutDataModel = SearcherAboutDataModel.getInstance()
export default searcherAboutDataModel as SearcherAboutDataModel
\ No newline at end of file
... ...
... ... @@ -116,6 +116,11 @@ export class HttpUrlUtils {
*/
static readonly APPOINTMENT_OPERATION_STATUS_PATH: string = "/api/live-center-message/zh/c/live/subscribe";
/**
* 首页 搜索提示
*/
static readonly SEARCH_HINT_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hints";
private static hostUrl: string = HttpUrlUtils.HOST_UAT;
static getCommonHeaders(): HashMap<string, string> {
... ... @@ -298,6 +303,11 @@ export class HttpUrlUtils {
return url
}
static getSearchHintDataUrl() {
let url = HttpUrlUtils.HOST_SIT + HttpUrlUtils.SEARCH_HINT_DATA_PATH
return url
}
/**
* 点赞操作
... ...
... ... @@ -9,5 +9,8 @@ export class SpConstants{
static USER_LONG_TIME_NO_LOGIN_MARK="longTimeNoLoginMark"
static USER_STATUS="user_status"
static USER_TEMP_TOKEN="tempToken"
//协议相关
static USER_PROTOCOL = "user_protocol" //用户协议
static PRIVATE_PROTOCOL = "private_protocol" //隐私协议
}
\ No newline at end of file
... ...
... ... @@ -34,4 +34,6 @@ export { PermissionUtil } from './src/main/ets/utils/PermissionUtil'
export { UserDataLocal } from './src/main/ets/utils/UserDataLocal'
export { NumberFormatterUtils } from './src/main/ets/utils/NumberFormatterUtils'
\ No newline at end of file
export { NumberFormatterUtils } from './src/main/ets/utils/NumberFormatterUtils'
// export { PermissionUtils } from './src/main/ets/utils/PermissionUtils'
\ No newline at end of file
... ...
... ... @@ -22,6 +22,7 @@ export class Logger {
private static domain: number = 0xFF00;
private static prefix: string = 'SightApp';
private static format: string = `%{public}s, %{public}s`;
static isDebug: boolean = true;
/**
* constructor.
... ... @@ -35,26 +36,44 @@ export class Logger {
}
static debug(...args: string[]) {
if(!Logger.isDebug){
return
}
hilog.debug(Logger.domain, Logger.prefix, Logger.format, args);
}
static info(...args: string[]) {
if(!Logger.isDebug){
return
}
hilog.info(Logger.domain, Logger.prefix, Logger.format, args);
}
static warn(...args: string[]) {
if(!Logger.isDebug){
return
}
hilog.warn(Logger.domain, Logger.prefix, Logger.format, args);
}
static error(...args: string[]) {
if(!Logger.isDebug){
return
}
hilog.error(Logger.domain, Logger.prefix, Logger.format, args);
}
static fatal(...args: string[]) {
if(!Logger.isDebug){
return
}
hilog.fatal(Logger.domain, Logger.prefix, Logger.format, args);
}
static isLoggable(level: LogLevel) {
if(!Logger.isDebug){
return
}
hilog.isLoggable(Logger.domain, Logger.prefix, level);
}
}
... ...
// import { abilityAccessCtrl, bundleManager, common, Permissions, Want } from '@kit.AbilityKit'
// import { BusinessError } from '@kit.BasicServicesKit'
// import { AppUtils } from './AppUtils'
// import { Logger } from './Logger'
//
// /**
// * 权限工具类
// * */
// export class PermissionUtils {
// //相机权限
// static CAMERA: Permissions = 'ohos.permission.CAMERA'
// //文件权限
// static READ_MEDIA: Permissions = 'ohos.permission.READ_MEDIA'
// static WRITE_MEDIA: Permissions = 'ohos.permission.WRITE_MEDIA'
// private static tokenId: number = 0
//
// /**检查权限是否授权*/
// static async checkPermissions(permission: Permissions): Promise<boolean> {
// let hasPermissions = false;
// let grantStatus: abilityAccessCtrl.GrantStatus = await PermissionUtils.checkAccessToken(permission);
//
// if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
// // 已经授权,可以继续访问目标操作
// hasPermissions = true;
// } else {
// hasPermissions = false;
// // 申请日历权限
// }
// return hasPermissions;
// }
//
// /**动态申请权限*/
// static reqPermissionsFromUser(permissions: Array<Permissions>, component: Object): Promise<boolean> {
//
// return new Promise((resolve, fail) => {
// let context = getContext(component) as common.UIAbilityContext;
// let atManager = abilityAccessCtrl.createAtManager();
// atManager.requestPermissionsFromUser(context, permissions).then((data) => {
// let grantStatus: Array<number> = data.authResults;
// let length: number = grantStatus.length;
//
// for (let i = 0; i < length; i++) {
// if (grantStatus[i] === 0) {
// // 用户授权,可以继续访问目标操作
// resolve(true);
// } else {
// resolve(false)
// }
// }
// }).catch((err: Error) => {
// fail(err)
// })
// });
// }
//
// /**跳转设置页面*/
// static openPermissionsInSystemSettings(context: Object): void {
// let uiContext = getContext(context) as common.UIAbilityContext;
// let wantInfo: Want = {
// bundleName: 'com.huawei.hmos.settings',
// abilityName: 'com.huawei.hmos.settings.MainAbility',
// uri: 'application_info_entry',
// parameters: {
// pushParams: AppUtils.getPackageName(uiContext) // 打开指定应用的设置页面
// }
// }
// uiContext.startAbility(wantInfo)
// }
//
// private static async checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
// let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
//
// // 获取应用程序的accessTokenID
// if (PermissionUtils.tokenId == 0) {
// try {
// let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
// let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
// PermissionUtils.tokenId = appInfo.accessTokenId;
// } catch (error) {
// const err: BusinessError = error as BusinessError;
// }
// }
// // 校验应用是否被授予权限
// try {
// grantStatus = await atManager.checkAccessToken(PermissionUtils.tokenId, permission);
// } catch (error) {
// const err: BusinessError = error as BusinessError;
// }
//
// return grantStatus;
// }
//
// }
\ No newline at end of file
... ...
... ... @@ -169,6 +169,10 @@ export class HttpUrlUtils {
*/
static readonly FOLLOW_OPERATION_PATH: string = "/api/rmrb-interact/interact/zh/c/attention/operation";
/**
* 首页 搜索提示
*/
static readonly SEARCH_HINT_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hints";
/**
* 早晚报列表
* 根据页面id获取页面楼层列表
* https://pdapis.pdnews.cn/api/rmrb-bff-display-zh/display/zh/c/pageInfo?pageId=28927
... ... @@ -390,7 +394,7 @@ export class HttpUrlUtils {
}
static getLogoutUrl() {
let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/logout";
let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/appLogout";
return url;
}
... ... @@ -419,6 +423,10 @@ export class HttpUrlUtils {
let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/auth/zh/c/checkVerifyCode";
return url;
}
static getAgreement() {
let url = HttpUrlUtils._hostUrl + "/api/rmrb-bff-display-zh/display/zh/c/agreement";
return url;
}
static getCheckVerifyByTokenCodeUrl() {
let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/auth/zh/c/checkVerifyCodeByToken";
... ... @@ -510,6 +518,12 @@ export class HttpUrlUtils {
return url
}
static getSearchHintDataUrl() {
let url = HttpUrlUtils._hostUrl + HttpUrlUtils.SEARCH_HINT_DATA_PATH
return url
}
// static getYcgCommonHeaders(): HashMap<string, string> {
// let headers: HashMap<string, string> = new HashMap<string, string>()
... ...
... ... @@ -58,3 +58,5 @@ export { AudioDetailComponent } from "./src/main/ets/components/AudioDetailCompo
export { BroadcastPageComponent } from "./src/main/ets/components/broadcast/BroadcastPageComponent"
export { FirstTabTopSearchComponent } from "./src/main/ets/components/search/FirstTabTopSearchComponent"
... ...
import { CompInfoBean, CompDTO } from 'wdBean'
import { CompInfoBean, CompDTO, CompList } from 'wdBean'
import { CommonConstants } from 'wdConstant';
import { ProcessUtils } from '../../utils/ProcessUtils';
/**
* 播报--今日推荐列表
*/
... ... @@ -9,6 +8,12 @@ import { ProcessUtils } from '../../utils/ProcessUtils';
@Component
export struct RecommendLists {
@Prop recommendCompInfoBean: CompInfoBean = {} as CompInfoBean // 推荐-组件信息
recommendDialog: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
recommendLists: this.recommendCompInfoBean?.compList
}),
offset: { dx: 0, dy: 0 }
})
build() {
Column(){
... ... @@ -32,7 +37,7 @@ export struct RecommendLists {
.justifyContent(FlexAlign.Center)
.margin({top: 5})
.onClick(() => {
// console.log(1)
this.recommendDialog.open()
})
}
}
... ... @@ -62,9 +67,65 @@ export struct RecommendLists {
ProcessUtils.processPage(item.operDataList[0])
})
}
}
@Builder
recommendListItem() {
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
@Prop recommendLists: CompList[]
build() {
Column(){
Text('推荐列表')
.fontSize($r('app.float.selected_text_size'))
.fontWeight(500)
.fontColor($r('app.color.color_323232'))
.height(57)
.width(CommonConstants.FULL_WIDTH)
.padding({left: 16})
Divider()
List(){
ForEach(this.recommendLists, (item: CompDTO, index: number) => {
ListItem(){
this.listItem(item, index)
}
.onClick(() => {
ProcessUtils.processPage(item.operDataList[0])
this.controller.close()
})
})
}.layoutWeight(1)
Divider()
Text('取消')
.fontSize($r('app.float.font_size_16'))
.fontColor($r('app.color.color_323232'))
.width(CommonConstants.FULL_WIDTH)
.height(57)
.textAlign(TextAlign.Center)
.onClick(() => {
this.controller.close()
})
}
.height('80%')
}
@Builder listItem(item: CompDTO,index: number) {
Row(){
Text(String(index+1))
.width(24)
.height(24)
.textAlign(TextAlign.Center)
.fontSize($r('app.float.font_size_14'))
.fontColor($r('app.color.color_48505A'))
Text(item.operDataList[0].newsTitle)
.layoutWeight(1)
.maxLines(1)
.textOverflow({overflow:TextOverflow.Ellipsis})
.margin({left: 16})
.fontSize($r('app.float.font_size_16'))
.fontColor($r('app.color.color_212228'))
}
.width(CommonConstants.FULL_WIDTH)
.height(54)
.padding({left: 16, right: 16})
}
}
\ No newline at end of file
... ...
... ... @@ -29,7 +29,8 @@ struct ChannelDialog {
@Link myChannelList: TopNavDTO[]
@Link moreChannelList: TopNavDTO[]
@Link localChannelList: TopNavDTO[]
@Link indexSettingArray: string[]
@Link homeChannelList: TopNavDTO[]
@Link indexSettingChannelId: number
controller?: CustomDialogController
confirm: (index: number) => void = () => {
}
... ... @@ -48,9 +49,6 @@ struct ChannelDialog {
let targetItem = this.myChannelList[newIndex]
if (!(targetItem?.headlinesOn === 1 || targetItem?.movePermitted === 0 || targetItem?.homeChannel === '1')) {
this.changeChannelIndex(index, newIndex)
if (index <= this.currentTopNavSelectedIndex || newIndex <= this.currentTopNavSelectedIndex) {
// this.currentTopNavSelectedIndex = this.myChannelList.findIndex(ele => ele.channelId === currentTopNavSelectedItem.channelId)
}
}
}
... ... @@ -214,22 +212,22 @@ struct ChannelDialog {
ListItem() {
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
ForEach(this.indexSettingArray, (text: string, index: number) => {
ForEach(this.homeChannelList, (item: TopNavDTO, index: number) => {
Stack() {
Image(this.indexSettingTabIndex === index ? $r('app.media.index_setting_button_active') : $r('app.media.index_setting_button'))
Image(item.channelId === this.indexSettingChannelId ? $r('app.media.index_setting_button_active') : $r('app.media.index_setting_button'))
.objectFit(ImageFit.Auto)
.rotate({
angle: index === 1 ? 180 : 0
})
Row() {
if (index === 0) {
Image(this.indexSettingTabIndex === index ? $r('app.media.recommend_icon') : $r('app.media.recommend_icon_active'))
Image(item.channelId === this.indexSettingChannelId ? $r('app.media.recommend_icon') : $r('app.media.recommend_icon_active'))
.width(20)
}
Text(text)
Text(item.name)
.textAlign(TextAlign.Center)
.fontSize(16)
.fontColor(index === this.indexSettingTabIndex ? '#ffffff' : '#ED2800')
.fontColor(item.channelId === this.indexSettingChannelId ? '#ffffff' : '#ED2800')
}
.width('100%')
.justifyContent(FlexAlign.Center)
... ... @@ -237,7 +235,7 @@ struct ChannelDialog {
.alignContent(Alignment.Start)
.height(36)
.onClick(() => {
this.indexSettingTabIndex = index
AppStorage.set('indexSettingChannelId',item.channelId)
})
})
}
... ... @@ -280,7 +278,7 @@ struct ChannelDialog {
.fontSize(14)
.fontColor(this.currentTopNavSelectedItem.channelId === item.channelId ? '#ED2800' : (item.homeChannel === '1' || item.movePermitted === 0 ? '#999999' : '#222222'))
if (this.isEditIng && item.myChannel !== '1') {
if (this.isEditIng && item.delPermitted === 1) {
Image($r('app.media.icon_audio_close'))
.width(12)
.margin({ left: 1 })
... ... @@ -292,7 +290,7 @@ struct ChannelDialog {
.backgroundColor(item.homeChannel === '1' || item.movePermitted === 0 ? '#F5F5F5' : '#ffffff')
.onClick(() => {
if (this.isEditIng) {
if (item.myChannel !== '1') {
if (item.delPermitted === 1) {
this.delChannelItem(index)
}
} else {
... ... @@ -445,10 +443,13 @@ struct ChannelSubscriptionLayout {
@State indexSettingArray: string [] = ['推荐', '热点']
//当前选中的频道
@Link currentTopNavSelectedIndex: number;
@Prop homeChannelList: TopNavDTO []
@Prop indexSettingChannelId: number
@Link myChannelList: TopNavDTO []
@Link moreChannelList: TopNavDTO []
@Link localChannelList: TopNavDTO []
@Link @Watch('onChannelIdsUpdate') channelIds: number []
@Link channelIds: number []
@StorageLink('channelIds') storeChannelIds: string = ''
changeTab: (index: number) => void = () => {
}
//频道弹窗点击切换频道
... ... @@ -461,11 +462,13 @@ struct ChannelSubscriptionLayout {
let channelIdTmp = this.channelIds.splice(index1, 1)
this.myChannelList.splice(index2, 0, tmp[0])
this.channelIds.splice(index2, 0, channelIdTmp[0])
this.storeChannelIds = this.channelIds.join(',')
}
//删除频道
delChannelItem = (index: number) => {
let item = this.myChannelList.splice(index, 1)[0]
this.channelIds.splice(index, 1)
this.storeChannelIds = this.channelIds.join(',')
if (item.moreChannel === '1') {
this.moreChannelList.unshift(item)
}
... ... @@ -477,6 +480,7 @@ struct ChannelSubscriptionLayout {
addChannelItem = (item: TopNavDTO) => {
this.channelIds.push(item.channelId)
this.myChannelList.push(item)
this.storeChannelIds = this.channelIds.join(',')
}
// @State currentTopNavSelectedIndex: number = 0
// @State topNavList: TopNavDTO [] = [
... ... @@ -1987,7 +1991,8 @@ struct ChannelSubscriptionLayout {
dialogController: CustomDialogController | null = new CustomDialogController({
builder: ChannelDialog({
currentTopNavSelectedIndex: $currentTopNavSelectedIndex,
indexSettingArray: $indexSettingArray,
indexSettingChannelId: $indexSettingChannelId,
homeChannelList: $homeChannelList,
myChannelList: $myChannelList,
moreChannelList: $moreChannelList,
localChannelList: $localChannelList,
... ... @@ -2049,13 +2054,8 @@ struct ChannelSubscriptionLayout {
// })
// }
onChannelIdsUpdate(){
AppStorage.SetOrCreate('channelIds', this.channelIds.join(','));
console.log(`AppStorage.get('channelIds')${AppStorage.get('channelIds')}`)
}
aboutToAppear() {
console.log(`myChannelListzz${this.channelIds}}`)
// this.topNavListHandle()
}
... ...
... ... @@ -64,13 +64,15 @@ export struct MinePageComponent {
//Grid 区域
MinePagePersonFunctionUI({personalData:$personalData,isLogin:this.isLogin})
//Card
MinePageCardUI()
//MinePageCardUI()
//创作者区域
MinePageCreatorFunctionUI({creatorData:$creatorData})
//MinePageCreatorFunctionUI({creatorData:$creatorData})
//更多功能
MinePageMoreFunctionUI({moreData:$moreData})
}.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
}
@Styles setFullWidthAndHeight(){
... ...
... ... @@ -3,10 +3,13 @@ import { LazyDataSource, Logger } from 'wdKit';
import { WDRouterRule } from 'wdRouter';
import { PageComponent } from './PageComponent';
import { ChannelSubscriptionLayout } from './ChannelSubscriptionLayout'
import { FirstTabTopSearchComponent } from '../search/FirstTabTopSearchComponent';
const TAG = 'TopNavigationComponent';
PersistentStorage.persistProp('channelIds', '');
PersistentStorage.persistProp('indexSettingChannelId', 0);
/**
* 顶部页签导航栏/顶导
*/
... ... @@ -19,10 +22,12 @@ export struct TopNavigationComponent {
// 顶导数据
@State @Watch('onTopNavigationDataUpdated') topNavList: TopNavDTO[] = []
@State compList: LazyDataSource<CompDTO> = new LazyDataSource();
@StorageProp('indexSettingChannelId') indexSettingChannelId: number = 0
//我的频道id列表
@State @Watch('onChannelIdsUpdate') channelIds: number[] = []
@State channelIds: number[] = []
//本地缓存频道id列表
@StorageProp('channelIds') storageChannelIds: string = ''
@State homeChannelList: TopNavDTO[] = []
// 我的频道列表
@State myChannelList: TopNavDTO[] = []
// 更多频道列表
... ... @@ -31,33 +36,48 @@ export struct TopNavigationComponent {
@State localChannelList: TopNavDTO[] = []
readonly MAX_LINE: number = 1;
//处理接口顶导数据
//处理新闻tab顶导频道数据
topNavListHandle() {
let _channelIds: number [] = []
let _myChannelList : TopNavDTO [] = []
let _myChannelList: TopNavDTO [] = []
let _storageChannelIds: string [] = [] //list1
let defaultMyChannelList: TopNavDTO[] = []
let handledTopNavList = [...this.topNavList]
handledTopNavList.sort((a, b) => {
let defaultList = [...this.topNavList]
defaultList.sort((a, b) => {
return a.num - b.num;
});
handledTopNavList.forEach(item => {
//defaultMyChannelList
defaultList.forEach(item => {
if (item.defaultPermitted === 1 || item.movePermitted === 0 || item.delPermitted === 0 || item.headlinesOn === 1) {
defaultMyChannelList.push(item);
}
if (item.defaultPermitted === 1) {
this.homeChannelList.push(item)
}
})
//有缓存频道id
if (this.storageChannelIds) {
_storageChannelIds = this.storageChannelIds.split(',')
}
defaultMyChannelList.forEach(item => {
item.myChannel = '1'
if (item.defaultPermitted === 1) {
item.homeChannel = '1'
}
let index = handledTopNavList.findIndex(_item => _item.channelId === item.channelId)
let index = defaultList.findIndex(_item => _item.channelId === item.channelId)
if (index !== -1) {
handledTopNavList.splice(index, 1)
defaultList.splice(index, 1)
}
})
handledTopNavList.unshift(...defaultMyChannelList)
handledTopNavList.forEach((item, index) => {
defaultList.unshift(...defaultMyChannelList)
defaultList.forEach((item, index) => {
if (this.storageChannelIds && _storageChannelIds.includes(String(item.channelId))) {
item.myChannel = '1'
}
if (item.channelType === 2) {
item.localChannel = '1'
}
... ... @@ -75,118 +95,102 @@ export struct TopNavigationComponent {
if (item.myChannel === '1') {
_myChannelList.push(item)
_channelIds.push(item.channelId)
}
if (item.moreChannel === '1') {
} else if (item.moreChannel === '1') {
this.moreChannelList.push(item)
}
if (item.localChannel === '1') {
} else if (item.localChannel === '1') {
this.localChannelList.push(item)
}
})
this.channelIds = _channelIds
this.myChannelList = _myChannelList
//缓存首页频道
if (!this.indexSettingChannelId) {
AppStorage.set('indexSettingChannelId', this.homeChannelList[0].channelId)
} else {
let index = this.myChannelList.findIndex(_item => _item.channelId === this.indexSettingChannelId)
if (index > -1) {
this.currentTopNavSelectedIndex = index
}
}
}
isBroadcast(item: TopNavDTO) {
return item.name === '播报'
}
isLayout(item: TopNavDTO) {
return item.name === '版面'
}
jumpToENewPaper() {
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
pageID: 'E_NEWSPAPER'
} as Params,
};
WDRouterRule.jumpWithAction(taskAction)
}
build() {
Column() {
// 顶部搜索、日报logo、早晚报
RelativeContainer() {
Stack({ alignContent: Alignment.Center }) {
Column() {
Row() {
FirstTabTopSearchComponent()
Image($r('app.media.background_search'))
.width('100%')
.height('100%')
.objectFit(ImageFit.Contain)
Image($r('app.media.icon_ren_min_ri_bao'))
.width(72)
.height(29)
.onClick((event: ClickEvent) => {
this.jumpToENewPaper()
})
Row() {
Image($r('app.media.icon_search'))
.width(18)
.height(18)
Text('河南大雪')
.fontColor($r('app.color.color_B0B0B0'))
.fontSize($r('app.float.font_size_13'))
Stack({ alignContent: Alignment.Center }) {
Image($r('app.media.background_read_paper_home'))
.width('100%')
.height('100%')
.objectFit(ImageFit.Contain)
Row() {
Image($r('app.media.icon_read_paper_home'))
.width(18)
.height(18)
Text('早晚报')
.fontColor($r('app.color.color_B0B0B0'))
.fontSize($r('app.float.font_size_13'))
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
.height(30)
.width(123)
.id('search')
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
center: { anchor: "__container__", align: VerticalAlign.Center }
})
Image($r('app.media.icon_ren_min_ri_bao'))
.width(72)
.height(29)
.onClick((event: ClickEvent) => {
.height(30)
.width(124)
.onClick(() => {
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
pageID: 'E_NEWSPAPER'
pageID: 'MorningEveningPaper'
} as Params,
};
WDRouterRule.jumpWithAction(taskAction)
})
.id('ren_min')
.alignRules({
middle: { anchor: "__container__", align: HorizontalAlign.Center },
center: { anchor: "__container__", align: VerticalAlign.Center }
})
Stack({ alignContent: Alignment.Center }) {
Image($r('app.media.background_read_paper_home'))
.width('100%')
.height('100%')
.objectFit(ImageFit.Contain)
Row() {
Image($r('app.media.icon_read_paper_home'))
.width(18)
.height(18)
Text('早晚报')
.fontColor($r('app.color.color_B0B0B0'))
.fontSize($r('app.float.font_size_13'))
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
.height(30)
.width(124)
.id('read')
.alignRules({
right: { anchor: "__container__", align: HorizontalAlign.End },
center: { anchor: "__container__", align: VerticalAlign.Center }
})
.onClick((event: ClickEvent) => {
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
pageID: 'MorningEveningPaper'
} as Params,
};
WDRouterRule.jumpWithAction(taskAction)
})
}.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.width('100%')
.height(40)
.padding({ top: 10 })
.backgroundColor($r('app.color.white'))
.visibility(this._currentNavIndex == 0 ? Visibility.Visible : Visibility.None)
// 频道分类list
Stack({ alignContent: Alignment.TopEnd }) {
Tabs({ controller: this.tabsController }) {
Tabs({ index: this.currentTopNavSelectedIndex, controller: this.tabsController }) {
ForEach(this._currentNavIndex === 0 ? this.myChannelList : this.topNavList, (navItem: TopNavDTO, index: number) => {
TabContent() {
if (!this.isBroadcast(navItem)) {
if (!this.isBroadcast(navItem) && !this.isLayout(navItem)) {
PageComponent({
currentTopNavSelectedIndex: $currentTopNavSelectedIndex,
navIndex: index,
... ... @@ -203,9 +207,12 @@ export struct TopNavigationComponent {
.vertical(false)
.onChange((index: number) => {
Logger.info(TAG, `onChange index : ${index}`);
if (!this.isBroadcast(this.myChannelList[index])) {
if (!this.isBroadcast(this._currentNavIndex === 0 ? this.myChannelList[index] : this.topNavList[index]) &&
!this.isLayout(this._currentNavIndex === 0 ? this.myChannelList[index] : this.topNavList[index])
) {
this.currentTopNavSelectedIndex = index;
} else {
}
if (this.isBroadcast(this._currentNavIndex === 0 ? this.myChannelList[index] : this.topNavList[index])) {
// 跳转到播报页面
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
... ... @@ -217,12 +224,18 @@ export struct TopNavigationComponent {
WDRouterRule.jumpWithAction(taskAction)
this.tabsController.changeIndex(this.currentTopNavSelectedIndex)
}
if (this.isLayout(this._currentNavIndex === 0 ? this.myChannelList[index] : this.topNavList[index])) {
this.jumpToENewPaper()
this.tabsController.changeIndex(this.currentTopNavSelectedIndex)
}
})
// 分类列表最右侧频道设置
if(this._currentNavIndex === 0){
if (this._currentNavIndex === 0) {
ChannelSubscriptionLayout({
currentTopNavSelectedIndex: $currentTopNavSelectedIndex,
indexSettingChannelId: this.indexSettingChannelId,
homeChannelList: this.homeChannelList,
myChannelList: $myChannelList,
moreChannelList: $moreChannelList,
localChannelList: $localChannelList,
... ... @@ -270,15 +283,12 @@ export struct TopNavigationComponent {
}
aboutToAppear() {
if(this._currentNavIndex === 0){
this.topNavListHandle()
}
//处理新闻tab顶导频道数据
this.topNavListHandle()
}
onChannelIdsUpdate() {
aboutToDisappear() {
AppStorage.set('channelIds', this.channelIds.join(','))
console.log(`PersistentStorage channelIds: ${this.channelIds}`)
console.log(`PersistentStorage aboutToAppear: ${this.storageChannelIds}`)
}
onTopNavigationDataUpdated() {
... ...
/**
* 首页顶部搜索导航栏
* 竖向滚动实现方案
* 方案一 使用动画 + 定时器
* 方案二 使用容器组件Swiper(当前)
*/
import SearcherAboutDataModel from '../../model/SearcherAboutDataModel'
const TAG = "FirstTabTopSearchComponent"
@Component
export struct FirstTabTopSearchComponent{
@State searchTextData :string[] = []
private swiperController: SwiperController = new SwiperController()
aboutToAppear(){
this.getSearchHint()
}
getSearchHint(){
SearcherAboutDataModel.getSearchHintData(getContext(this)).then((value)=>{
if(value!=null){
this.searchTextData = value
}
}).catch((err:Error)=>{
console.log(TAG,JSON.stringify(err))
})
}
build(){
Row(){
Image($r('app.media.icon_search'))
.width(18)
.height(18)
if(this.searchTextData!=null && this.searchTextData.length>0){
Swiper(this.swiperController) {
ForEach(this.searchTextData, (item: string, index: number ) => {
Text(item)
.fontWeight(400)
.fontColor($r('app.color.color_B0B0B0'))
.fontSize($r('app.float.font_size_13'))
.textAlign(TextAlign.Start)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Clip})
})
}
.loop(true)
.autoPlay(true)
.interval(3000)
.indicator(false)
.vertical(true)
.height(30)
}
}.height(30)
.width(124)
.padding({left:15})
.backgroundImage($r('app.media.background_search'))
.backgroundImageSize(ImageSize.Cover)
}
}
\ No newline at end of file
... ...
... ... @@ -12,6 +12,10 @@ import router from '@ohos.router';
import { WDRouterPage, WDRouterRule } from 'wdRouter';
import { Params } from 'wdBean';
import { SettingPasswordParams } from 'wdLogin';
import { LoginViewModel } from 'wdLogin/src/main/ets/pages/login/LoginViewModel';
import { Router } from '@ohos.arkui.UIContext';
import promptAction from '@ohos.promptAction';
export { SettingPasswordParams } from "wdLogin"
@Component
... ... @@ -83,16 +87,21 @@ export struct AccountAndSecurityLayout {
Column() {
Button('退出登录',{ stateEffect: true ,type: ButtonType.Normal}).width('90%').height('80lpx').backgroundColor('#da3e22').fontColor('#fff').margin('20lpx').borderRadius('8lpx').onClick(()=>{
AlertDialog.show({
title: '🥟id : ' + "button",
message: '标题:' + '退出登录',
confirm: {
value: "OK",
action: () => {
},
}
})
let login = new LoginViewModel;
promptAction.showToast({ message: '退出登录' })
login.logOut();
router.back();
router.back();
// AlertDialog.show({
// title: '🥟id : ' + "button",
// message: '标题:' + '退出登录',
// confirm: {
// value: "OK",
// action: () => {
//
// },
// }
// })
})
}
... ...
import { NewspaperListBean, NewspaperListItemBean, NewspaperPositionItemBean } from 'wdBean'
import { Action, NewspaperListBean, NewspaperListItemBean, NewspaperPositionItemBean, Params } from 'wdBean'
import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO'
import { WDRouterRule } from 'wdRouter/Index'
import { ENewspaperPageDialog } from '../dialog/ENewspaperPageDialog'
/**
... ... @@ -143,6 +145,24 @@ export struct ENewspaperListDialog {
}
}
.alignItems(HorizontalAlign.Start)
.onClick(() => {
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
contentID: '' + positionItem.newsId,
pageID: 'IMAGE_TEXT_DETAIL',
extra: {
relType: positionItem.relType ?? '',
relId: '' + positionItem.relId,
sourcePage: '5'
} as ExtraDTO
} as Params,
};
WDRouterRule.jumpWithAction(taskAction)
if (this.listDialogController) {
this.listDialogController.close()
}
})
}
})
... ...
import { Logger, ResourcesUtils } from 'wdKit';
import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork';
import HashMap from '@ohos.util.HashMap';
const TAG = "SearcherAboutDataModel"
/**
* 我的页面 所有数据 获取封装类
*/
class SearcherAboutDataModel{
private static instance: SearcherAboutDataModel;
private constructor() { }
/**
* 单例模式
* @returns
*/
public static getInstance(): SearcherAboutDataModel {
if (!SearcherAboutDataModel.instance) {
SearcherAboutDataModel.instance = new SearcherAboutDataModel();
}
return SearcherAboutDataModel.instance;
}
/**
* 首页 搜索提示滚动内容
*/
getSearchHintData(context: Context): Promise<string[]> {
return new Promise<string[]>((success, error) => {
Logger.info(TAG, `getSearchHintData start`);
this.fetchSearchHintData().then((navResDTO: ResponseDTO<string[]>) => {
if (!navResDTO || navResDTO.code != 0) {
success(this.getSearchHintDataLocal(context))
return
}
Logger.info(TAG, "getSearchHintData then,SearchHintDataResDTO.timeStamp:" + navResDTO.timestamp);
let navigationBean = navResDTO.data as string[]
success(navigationBean);
}).catch((err: Error) => {
Logger.error(TAG, `fetchSearchHintData catch, error.name : ${err.name}, error.message:${err.message}`);
success(this.getSearchHintDataLocal(context))
})
})
}
fetchSearchHintData() {
let url = HttpUrlUtils.getSearchHintDataUrl()
let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
return WDHttp.get<ResponseDTO<string[]>>(url, headers)
};
async getSearchHintDataLocal(context: Context): Promise<string[]> {
Logger.info(TAG, `getSearchHintDataLocal start`);
let compRes: ResponseDTO<string[]> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<string[]>>(context,'search_hint_data.json' );
if (!compRes || !compRes.data) {
Logger.info(TAG, `getSearchHintDataLocal compRes is empty`);
return []
}
Logger.info(TAG, `getSearchHintDataLocal compRes : ${JSON.stringify(compRes)}`);
return compRes.data
}
}
const searcherAboutDataModel = SearcherAboutDataModel.getInstance()
export default searcherAboutDataModel as SearcherAboutDataModel
\ No newline at end of file
... ...
... ... @@ -127,6 +127,14 @@
{
"name":"color_EEEEEE",
"value": "#EEEEEE"
},
{
"name": "color_323232",
"value": "#323232"
},
{
"name": "color_48505A",
"value": "#48505A"
}
]
}
\ No newline at end of file
... ...
... ... @@ -121,6 +121,7 @@ export class LoginModel {
bean['verifyCode'] = verifyCode
bean['phone'] = phone
let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
headers.set('cookie', '');
return new Promise<CheckVerifyBean>((success, fail) => {
HttpRequest.post<ResponseDTO<CheckVerifyBean>>(HttpUrlUtils.getCheckVerifyCodeUrl(), bean, headers).then((data: ResponseDTO<CheckVerifyBean>) => {
Logger.debug("LoginViewModel:success2 ", data.message)
... ... @@ -230,7 +231,7 @@ export class LoginModel {
return new Promise<string>((success, fail) => {
HttpRequest.post<ResponseDTO<string>>(HttpUrlUtils.getLogoutUrl(), bean, headers).then((data: ResponseDTO<string>) => {
if (!data || !data.data) {
if (!data) {
fail("数据为空")
return
}
... ... @@ -238,7 +239,7 @@ export class LoginModel {
fail(data.message)
return
}
success(data.data)
success('')
}, (error: Error) => {
fail(error.message)
Logger.debug("LoginViewModel:error ", error.toString())
... ...
... ... @@ -105,12 +105,12 @@ struct LoginPage {
Text() {
Span("我已阅读并同意").fontColor("#999999").fontSize(12)
Span("《用户协议》").fontColor("#ED2800").fontSize(12).onClick(() => {
let bean={contentId:"1",pageID:""} as Params
let bean={contentID:"1",pageID:""} as Params
WDRouterRule.jumpWithPage(WDRouterPage.loginProtocolPage,bean)
})
Span("及").fontColor("#999999").fontSize(12)
Span("《隐私政策》").fontColor("#ED2800").fontSize(12).onClick(() => {
let bean={contentId:"2",pageID:""} as Params
let bean={contentID:"2",pageID:""} as Params
WDRouterRule.jumpWithPage(WDRouterPage.loginProtocolPage,bean)
})
}
... ...
import router from '@ohos.router';
import webview from '@ohos.web.webview';
import { Logger } from 'wdKit';
import { SpConstants } from 'wdConstant/Index';
import { Logger, SPHelper } from 'wdKit';
import { Params } from '../../../../../../../commons/wdRouter/oh_modules/wdBean/src/main/ets/bean/content/Params';
... ... @@ -11,14 +12,20 @@ const TAG = 'LoginProtocolWebview';
struct LoginProtocolWebview {
webUrl: string = ''
webviewController: webview.WebviewController = new webview.WebviewController()
userProtocol = "https://cdnpeoplefrontuat.aikan.pdnews.cn/rmrb/rmrb-protocol-zh-web/0.0.1/app/protocol-1005.html"
privateProtocol = 'https://cdnpeoplefrontuat.aikan.pdnews.cn/rmrb/rmrb-protocol-zh-web/0.0.1/app/protocol-1001.html'
aboutToAppear() {
async aboutToAppear() {
if (router.getParams()) {
let params = router.getParams() as Params
Logger.info(TAG, 'params.contentID:' + params.contentID);
if (params.contentID == "1") {
this.webUrl = "https://cdnpeoplefrontuat.aikan.pdnews.cn/rmrb/rmrb-protocol-zh-web/0.0.1/app/protocol-1005.html"
this.webUrl = await SPHelper.default.get(SpConstants.USER_PROTOCOL, this.userProtocol) as string
this.webviewController.loadUrl(this.webUrl)
} else {
this.webUrl = "https://cdnpeoplefrontuat.aikan.pdnews.cn/rmrb/rmrb-protocol-zh-web/0.0.1/app/protocol-1001.html"
this.webUrl = await SPHelper.default.get(SpConstants.PRIVATE_PROTOCOL, this.privateProtocol) as string
this.webviewController.loadUrl(this.webUrl)
}
}
... ... @@ -33,7 +40,7 @@ struct LoginProtocolWebview {
.aspectRatio(1)
.onClick(() => {
router.back();
}).margin({left:16})
}).margin({ left: 16 })
Text()
}
.alignItems(VerticalAlign.Center)
... ...
... ... @@ -5,6 +5,8 @@ import { SPHelper } from 'wdKit'
import { CheckVerifyBean } from './CheckVerifyBean'
import cryptoFramework from '@ohos.security.cryptoFramework'
import buffer from '@ohos.buffer'
import { encryptMessage } from '../../utils/cryptoUtil'
import {
SpConstants
} from '../../../../../../../commons/wdNetwork/oh_modules/wdConstant/src/main/ets/constants/SpConstants'
... ... @@ -119,7 +121,8 @@ export class LoginViewModel {
//重置密码 需要老密码
resetPassword(password: string, tempToken: string) {
return new Promise<string>(async (success, fail) => {
let passwordNew = await this.doMd(password)
let passwordNew = await encryptMessage(password);
this.loginModel.resetPassword(passwordNew, tempToken).then((data) => {
success(data)
}).catch((message: string) => {
... ... @@ -132,7 +135,7 @@ export class LoginViewModel {
//忘记密码
forgotPassword(password: string, tempToken: string) {
return new Promise<string>(async (success, fail) => {
let passwordNew = await this.doMd(password)
let passwordNew = await encryptMessage(password)
this.loginModel.forgotPassword(passwordNew, tempToken).then((data) => {
success(data)
}).catch((message: string) => {
... ... @@ -146,9 +149,18 @@ export class LoginViewModel {
return new Promise<string>(async (success, fail) => {
this.loginModel.logOut().then((data) => {
//清除登录状态以及token、userid等信息
HttpUrlUtils.setUserId('');
HttpUrlUtils.setUserType('');
HttpUrlUtils.setUserToken('');
SPHelper.default.save(SpConstants.USER_FIRST_MARK, '')
SPHelper.default.save(SpConstants.USER_ID, '')
SPHelper.default.save(SpConstants.USER_JWT_TOKEN, '')
SPHelper.default.save(SpConstants.USER_LONG_TIME_NO_LOGIN_MARK, '')
SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, '')
SPHelper.default.save(SpConstants.USER_STATUS, '')
SPHelper.default.save(SpConstants.USER_Type, '')
SPHelper.default.save(SpConstants.USER_NAME, '')
HttpUrlUtils.setUserId("")
HttpUrlUtils.setUserType("")
HttpUrlUtils.setUserToken('')
success(data)
}).catch((message: string) => {
fail(message)
... ...
... ... @@ -188,7 +188,7 @@ export struct SettingPasswordLayout {
Row() {
TextInput({ placeholder: item.inputPlacholder })
.type(InputType.Password)
.showPasswordIcon(false)
.showPasswordIcon(true)
.backgroundColor('#00000000')
.onChange((value: string) => {
this.inputTextChange(value, item.inputTag)
... ...
import cryptoFramework from '@ohos.security.cryptoFramework';
import buffer from '@ohos.buffer';
import util from '@ohos.util';
// 加密消息
let pubKeyString = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI05e8RfyEnLW/Un629lVJoVHntIanEAETot5nRcLmPJpXbC5lf5UgvVrDPPmoTxc567Hg9qq3AyAqWrSyqI6MECAwEAAQ==';
async function encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
let cipher = cryptoFramework.createCipher('RSA1024|PKCS1');
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null);
let encryptData = await cipher.doFinal(plainText);
return encryptData;
}
// 解密消息
async function decryptMessagePromise(privateKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {
let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, privateKey, null);
let decryptData = await decoder.doFinal(cipherText);
return decryptData;
}
// 生成RSA密钥对
async function genKeyPairByData() {
let base64 = new util.Base64Helper();
let pubKeyData = base64.decodeSync(pubKeyString);
let pkData = new Uint8Array(buffer.from(pubKeyString, 'utf-8').buffer)
let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyData };
let pkData2 = new Uint8Array([48, 129, 159, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, 197, 64, 10, 198, 14, 110, 65, 92, 206, 35, 28, 123, 153, 24, 134, 255, 145, 74, 42, 173, 40, 215, 146, 58, 143, 46, 10, 195, 154, 160, 69, 196, 220, 152, 179, 44, 111, 200, 84, 78, 215, 73, 210, 181, 12, 29, 70, 68, 36, 135, 153, 89, 230, 202, 130, 212, 111, 243, 234, 92, 131, 62, 145, 50, 73, 48, 104, 245, 46, 70, 45, 157, 147, 143, 140, 162, 156, 216, 220, 49, 121, 142, 194, 33, 223, 201, 0, 16, 163, 210, 240, 118, 92, 147, 121, 220, 17, 114, 24, 52, 125, 135, 176, 88, 21, 83, 86, 17, 156, 88, 250, 48, 79, 86, 128, 248, 105, 208, 133, 140, 13, 153, 164, 191, 136, 164, 44, 53, 2, 3, 1, 0, 1]);
let pubKeyBlob2: cryptoFramework.DataBlob = { data: pkData2 };
let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024');
rsaGenerator.convertKey(pubKeyBlob2, null, (err, keyPair) => {
if (err) {
console.error(`convertKey failed, ${err.code}, ${err.message}`);
}
console.info('convertKey success');
});
rsaGenerator.convertKey(pubKeyBlob, null, (err, keyPair) => {
if (err) {
console.error(`convertKey failed, ${err.code}, ${err.message}`);
}
console.info('convertKey success');
});
let keyPair = await rsaGenerator.convertKey(pubKeyBlob, null)
console.info('convertKey success');
return keyPair;
}
export async function encryptMessage(text:string) {
let keyPair = await genKeyPairByData();
let pubKey = keyPair.pubKey;
let priKey = keyPair.priKey;
let message = text;
// 把字符串按utf-8解码为Uint8Array
let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
let encryptText = await encryptMessagePromise(pubKey, plainText);
//base 64加密
let base64 = new util.Base64Helper();
let result = base64.encodeToStringSync(encryptText.data);
return result;
}
\ No newline at end of file
... ...
export interface AgreementBean{
description:string
linkUrl:string
name:string
plat:string
system:string
versionCode:string
versionId:string
type:number
}
\ No newline at end of file
... ...
... ... @@ -8,6 +8,7 @@ import preferences from '@ohos.data.preferences'
import { GlobalContext } from '../../utils/GlobalContext'
import { WDRouterRule } from 'wdRouter';
import { WDRouterPage } from 'wdRouter';
import { LaunchModel } from '../viewModel/LaunchModel'
@Entry
@Component
... ... @@ -85,6 +86,7 @@ struct LaunchPage {
// let isJumpPrivacy: boolean = globalThis.isJumpPrivacy ?? false;
// let isJumpPrivacy: boolean = (GlobalContext.getContext().getObject('isJumpPrivacy') as boolean) ?? false;
//if (!isJumpPrivacy) {
this.requestAgreement()
this.dialogController.open();
// }
} else {
... ... @@ -146,6 +148,10 @@ struct LaunchPage {
}
requestAgreement() {
//请求隐私协议接口
let launchModel = new LaunchModel()
launchModel.getAgreement()
}
}
\ No newline at end of file
... ...
... ... @@ -83,7 +83,7 @@ export default struct CustomDialogComponent {
.fontColor(Color.Red)
.onClick(() => {
let bean={contentId:"1",pageID:""} as Params
let bean={contentID:"2",pageID:""} as Params
WDRouterRule.jumpWithPage(WDRouterPage.loginProtocolPage,bean)
//GlobalContext.getContext().setObject('isJumpPrivacy', true);
... ... @@ -100,7 +100,7 @@ export default struct CustomDialogComponent {
.fontColor(Color.Red)
.onClick(() => {
let bean={contentId:"2",pageID:""} as Params
let bean={contentID:"1",pageID:""} as Params
WDRouterRule.jumpWithPage(WDRouterPage.loginProtocolPage,bean)
//GlobalContext.getContext().setObject('isJumpPrivacy', true);
... ...
import { HttpUrlUtils, ResponseDTO } from 'wdNetwork/Index';
// import { HashMap } from '@kit.ArkTS';
import HashMap from '@ohos.util.HashMap';
import { AgreementBean } from '../launchPage/AgreementBean';
import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest';
import { Logger, SPHelper } from 'wdKit/Index';
import { SpConstants } from 'wdConstant/Index';
export class LaunchModel {
getAgreement() {
let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
return new Promise<AgreementBean>((success, fail) => {
HttpRequest.get<ResponseDTO<Array<AgreementBean>>>(HttpUrlUtils.getAgreement(), headers).then((data: ResponseDTO<Array<AgreementBean>>) => {
if (!data || !data.data) {
fail("数据为空")
return
}
if (data.code != 0) {
fail(data.message)
return
}
Logger.debug("LaunchModel:success2 ", JSON.stringify(data))
//保存数据
for (let i = 0; i < data.data.length; i++) {
if (data.data[i].type == 1) {
SPHelper.default.save(SpConstants.USER_PROTOCOL, data.data[i].linkUrl)
} else if (data.data[i].type == 2) {
SPHelper.default.save(SpConstants.PRIVATE_PROTOCOL, data.data[i].linkUrl)
}
}
}, (error: Error) => {
Logger.debug("LaunchModel:error2 ", error.toString())
fail(error.message)
})
})
}
}
\ No newline at end of file
... ...
{
"code": "0",
"data": [
"习语",
"党史学习",
"高考倒计时"
],
"message": "Success",
"success": true,
"timestamp": 1712562841885
}
\ No newline at end of file
... ...