├── .gitignore
├── AppScope
├── app.json5
└── resources
│ └── base
│ ├── element
│ └── string.json
│ └── media
│ └── app_icon.png
├── README.md
├── build-profile.json5
├── entry
├── .gitignore
├── build-profile.json5
├── hvigorfile.ts
├── oh-package.json5
└── src
│ ├── main
│ ├── ets
│ │ ├── api
│ │ │ ├── HttpConfig.ets
│ │ │ ├── HttpRequest.ets
│ │ │ ├── HttpService.ets
│ │ │ └── ResponseResult.ets
│ │ ├── bean
│ │ │ ├── ArticleBean.ets
│ │ │ ├── BannerBean.ets
│ │ │ ├── CoinBean.ets
│ │ │ ├── MsgBean.ets
│ │ │ ├── ProjectBean.ets
│ │ │ ├── RankBean.ets
│ │ │ ├── SettingItem.ets
│ │ │ ├── TreeBean.ets
│ │ │ └── UserInfoBean.ets
│ │ ├── common
│ │ │ ├── bean
│ │ │ │ └── BottomTabsItem.ets
│ │ │ └── constants
│ │ │ │ └── Constants.ets
│ │ ├── entryability
│ │ │ └── EntryAbility.ets
│ │ ├── pages
│ │ │ ├── HomePage.ets
│ │ │ ├── InfoPage.ets
│ │ │ ├── LoginRegisterPage.ets
│ │ │ ├── MainPage.ets
│ │ │ ├── MePage.ets
│ │ │ ├── MsgPage.ets
│ │ │ ├── ProjectPage.ets
│ │ │ ├── SettingPage.ets
│ │ │ ├── Splash.ets
│ │ │ ├── TreePage.ets
│ │ │ ├── TreeTabPage.ets
│ │ │ └── WebPage.ets
│ │ ├── utils
│ │ │ ├── Logger.ets
│ │ │ ├── PreferencesUtils.ets
│ │ │ └── Utils.ets
│ │ ├── view
│ │ │ ├── ArticleItem.ets
│ │ │ ├── InfoItem.ets
│ │ │ ├── MineFunc.ets
│ │ │ ├── MineHead.ets
│ │ │ ├── MsgItemView.ets
│ │ │ ├── MsgReadList.ets
│ │ │ ├── MsgUnreadList.ets
│ │ │ ├── ProjectList.ets
│ │ │ ├── TitleBar.ets
│ │ │ └── TreeList.ets
│ │ └── viewmodel
│ │ │ ├── BottomTabsModel.ets
│ │ │ ├── HomeViewModel.ets
│ │ │ ├── InfoViewModel.ets
│ │ │ ├── LoginRegisterViewModel.ets
│ │ │ ├── MeViewModel.ets
│ │ │ ├── MsgViewModel.ets
│ │ │ ├── NavigatorModel.ets
│ │ │ ├── ProjectViewModel.ets
│ │ │ ├── SettingViewModel.ets
│ │ │ └── TreeViewModel.ets
│ ├── module.json5
│ └── resources
│ │ ├── base
│ │ ├── element
│ │ │ ├── color.json
│ │ │ ├── float.json
│ │ │ └── string.json
│ │ ├── media
│ │ │ ├── ic_about.png
│ │ │ ├── ic_arrow_left.png
│ │ │ ├── ic_arrow_right.png
│ │ │ ├── ic_clock.png
│ │ │ ├── ic_home_normal.png
│ │ │ ├── ic_home_selected.png
│ │ │ ├── ic_language.png
│ │ │ ├── ic_logo.png
│ │ │ ├── ic_me_normal.png
│ │ │ ├── ic_me_selected.png
│ │ │ ├── ic_msg_normal.png
│ │ │ ├── ic_msg_selected.png
│ │ │ ├── ic_nav_normal.png
│ │ │ ├── ic_nav_selected.png
│ │ │ ├── ic_project_normal.png
│ │ │ ├── ic_project_selected.png
│ │ │ ├── ic_setting.png
│ │ │ ├── ic_theme.png
│ │ │ ├── ic_user.png
│ │ │ ├── icon.png
│ │ │ └── splash_bg.png
│ │ └── profile
│ │ │ └── main_pages.json
│ │ ├── en_US
│ │ └── element
│ │ │ └── string.json
│ │ └── zh_CN
│ │ └── element
│ │ └── string.json
│ └── ohosTest
│ ├── ets
│ ├── test
│ │ ├── Ability.test.ets
│ │ └── List.test.ets
│ ├── testability
│ │ ├── TestAbility.ets
│ │ └── pages
│ │ │ └── Index.ets
│ └── testrunner
│ │ └── OpenHarmonyTestRunner.ts
│ ├── module.json5
│ └── resources
│ └── base
│ ├── element
│ ├── color.json
│ └── string.json
│ ├── media
│ └── icon.png
│ └── profile
│ └── test_pages.json
├── hvigor
└── hvigor-config.json5
├── hvigorfile.ts
├── oh-package-lock.json5
├── oh-package.json5
└── video
└── wanandroidhm.mp4
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /oh_modules
3 | /local.properties
4 | /.idea
5 | **/build
6 | /.hvigor
7 | .cxx
8 | /.clangd
9 | /.clang-format
10 | /.clang-tidy
11 | **/.test
--------------------------------------------------------------------------------
/AppScope/app.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "bundleName": "com.pgzxc.wanandroidhm",
4 | "vendor": "example",
5 | "versionCode": 1000000,
6 | "versionName": "1.0.0",
7 | "icon": "$media:app_icon",
8 | "label": "$string:app_name"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/AppScope/resources/base/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "app_name",
5 | "value": "WanAndroidHM"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/AppScope/resources/base/media/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/AppScope/resources/base/media/app_icon.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 一 项目演示
2 |
3 | 视频演示
4 |
5 |
8 |
9 | B站链接:[https://www.bilibili.com/video/BV1Ku4y1w7St](https://www.bilibili.com/video/BV1Ku4y1w7St)
10 |
11 | 项目预览
12 |
13 | | ![][waz-hm-1] | ![][waz-hm-2] | ![][waz-hm-3] | ![][waz-hm-4] |
14 | | :-----------: | :------------: | :------------: | :------------: |
15 | | ![][waz-hm-5] | ![][waz-hm-6] | ![][waz-hm-7] | ![][waz-hm-8] |
16 | | ![][waz-hm-9] | ![][waz-hm-10] | ![][waz-hm-11] | ![][waz-hm-12] |
17 | | ![][waz-hm-13]| ![][waz-hm-14] |![][waz-hm-15] | ![][waz-hm-16] |
18 |
19 |
20 | ## 二 开发环境
21 |
22 | * 操作系统:Windows 11 专业版 22H2
23 | * 开发工具:DevEco Studio 4.0 Release版本
24 | * 开发语言:ArkTS
25 | * node.js:v16.20.1
26 | * ohpm:1.2.5
27 |
28 | ## 三 基础知识
29 |
30 | * ArkTS语法(基本语法、状态管理、渲染控制)
31 | * UI(ArkTS声明式开发)及预览
32 | * HTTP数据请求
33 |
34 | ## 四 开发进度
35 |
36 | ### 4.1 v1.0
37 |
38 | * 启动页+底部导航框架
39 | * 底部导航框架使用:Tabs+tabBar
40 | * 在entryability/EntryAbility.ts的windowStage.loadContent中表明启动显示页面
41 | * 在resources/base/profile/main_pages.json添加Pages页面
42 |
43 | ### 4.2 v2.0
44 |
45 | * 网络请求框架(HttpService(网络请求封装)+ResponseResult(返回结果)+HttpRequest(网络请求Promise)+HttpConfig(相关配置))
46 | * Stage模型,在module.json5配置文件中声明权限(比如网络权限`ohos.permission.INTERNET`)
47 | * bean包将接口返回结果封装成数据Bean
48 | * viewmodel中Promise+async解析结果数据为Bean
49 | * Page页面aboutToAppear(页面即将显示)方法中调用viewmodel中的接口
50 |
51 | ### 4.3 v3.0
52 |
53 | * 使用UI容器(Scroll、Row、Column、List)和常用组件Text、Image搭建UI界面
54 | * 自定义组件用于List-ListItem使用
55 | * Swiper实现轮播图
56 | * @State实现数据变化监听
57 | * 样式文件实现复杂布局
58 | * Resource:color-颜色命名文字不能大写,float-fp后缀对应文字,vp后缀对应宽度长度
59 |
60 | ### 4.4 v4.0
61 |
62 | * ForEach循环生成多组件
63 | * ListItemGroup分组列表组件
64 | * Flex弹性布局组件
65 | * 导航页面
66 |
67 | ### 4.5 v5.0
68 |
69 | * Tabs+ForEach(TabContent(TreeList-数据列表)+tabBar)组件展示各Tab标题下对应的列表
70 | * `@Watch装饰器`:状态变量更改通知。@Watch('changeTab')中声明changeTab方法
71 | * `@Link装饰器`:父子双向同步。@Link currentIndex: number中父组件ProjectPage传递当前tabIndex给ProjectList用于展示列表数据
72 | * 项目界面
73 |
74 | ### 4.6 v6.0
75 |
76 | 1- 布局
77 |
78 | * 消息
79 | * 我的
80 | * 登录、注册
81 | * 设置
82 | * 导航-知识体系下的文章
83 | * WebView显示网页内容
84 |
85 | 2-技术点
86 |
87 | * Preferences、PersistentStorage保存永久性数据
88 | * 组件:GridRow、GridCol、webview等
89 | * 页面间转场动画:pageTransition
90 | * 登录和注册成功后,保存cookie到PersistentStorage中,再次请求时,从AppStorage中获取cookie
91 | * 页面间导航:
92 | - 1-router(router.pushUrl({url: 'pages/Detail',urlparams: paramsInfo});
93 | - 2-Navigator({ target:url, type: NavigationType.Push }) {}.params({key:value}
94 | * 参数获取
95 | - const params = router.getParams(); // 获取传递过来的参数对象
96 | - const id = params['id']; // 获取id属性的值
97 |
98 | ### 4.7 v7.0(版本升级)
99 | * OpenHarmony 3.1.1 Release 升级到OpenHarmony 4.0 Release
100 | * hvigor中hvigorVersion从2.4.2升级到3.0.9
101 |
102 | ### 4.8 v8.0
103 | * 导入下拉刷新库@ohos/pulltorefresh (V2.0.1)——说明,最新版本适配api10,不适用于当前项目
104 | * home页面添加下拉刷新和上拉加载功能
105 |
106 | ### 4.9 v9.0
107 |
108 | * 项目/导航 页添加刷新和加载更多功能
109 | * 去掉module.json5中为了预览添加的@Entry装饰器
110 |
111 | ### 4.10 v10.0
112 |
113 | * 我的-积分,跳转积分页面
114 | * 我的-排行,跳转排行页面
115 |
116 | ### 4.11 v11.0
117 | * api9升级到api10
118 | * api升级过程中出现的问题及解决办法
119 |
120 | ```
121 | 1. 'params' is possibly 'undefined'. \
122 | 2. Not all code paths return a value. \
123 | 3. Use explicit types instead of "any", "unknown" (arkts-no-any-unknown)
124 | 4. Argument of type 'Tag[]' is not assignable to parameter of type 'string'.
125 | 5. Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)
126 | 6. Array literals must contain elements of only inferrable types (arkts-no-noninferrable-arr-literals) \
127 | 7. Type 'null' is not assignable to type 'UserData'. \
128 | 8. try catch报错
129 | 9. 传值null问题
130 | ```
131 |
132 |
133 |
134 | [waz-hm-1]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-splash-0.png
135 | [waz-hm-2]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-home-1.png
136 | [waz-hm-3]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-nav-2.png
137 | [waz-hm-4]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-navlist-3.png
138 | [waz-hm-5]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-project-4.png
139 | [waz-hm-6]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-msg-5.png
140 | [waz-hm-7]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-msg-6.png
141 | [waz-hm-8]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-me-7.png
142 | [waz-hm-9]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-me-8.png
143 | [waz-hm-10]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-login-9.png
144 | [waz-hm-11]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-register-10.png
145 | [waz-hm-12]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-me-set-11.png
146 | [waz-hm-13]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-home-refresh-12.png
147 | [waz-hm-14]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-home-loadmore-13.png
148 | [waz-hm-15]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-rank-14.png
149 | [waz-hm-16]:https://jsd.onmicrosoft.cn/gh/PGzxc/CDN/blog-resume/waz-hm-coin-15.png
--------------------------------------------------------------------------------
/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "signingConfigs": [],
4 | "products": [
5 | {
6 | "name": "default",
7 | "signingConfig": "default",
8 | "compatibleSdkVersion": "4.0.0(10)",
9 | "runtimeOS": "HarmonyOS"
10 | }
11 | ]
12 | },
13 | "modules": [
14 | {
15 | "name": "entry",
16 | "srcPath": "./entry",
17 | "targets": [
18 | {
19 | "name": "default",
20 | "applyToProducts": [
21 | "default"
22 | ]
23 | }
24 | ]
25 | }
26 | ]
27 | }
--------------------------------------------------------------------------------
/entry/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /oh_modules
3 | /.preview
4 | /build
5 | /.cxx
6 | /.test
--------------------------------------------------------------------------------
/entry/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "apiType": 'stageMode',
3 | "buildOption": {
4 | },
5 | "targets": [
6 | {
7 | "name": "default",
8 | "runtimeOS": "HarmonyOS"
9 | },
10 | {
11 | "name": "ohosTest",
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/entry/hvigorfile.ts:
--------------------------------------------------------------------------------
1 | // Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
2 | export { hapTasks } from '@ohos/hvigor-ohos-plugin';
3 |
--------------------------------------------------------------------------------
/entry/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "name": "entry",
3 | "version": "1.0.0",
4 | "description": "Please describe the basic information.",
5 | "main": "",
6 | "author": "",
7 | "license": "",
8 | "dependencies": {}
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/entry/src/main/ets/api/HttpConfig.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * @desc:网络请求相关配置
3 | */
4 |
5 | export default class HttpConfig {
6 | /**
7 | * The host address of the server.
8 | */
9 | static readonly baseURL: string = 'https://www.wanandroid.com/';
10 |
11 | //1-首页
12 | static readonly bannerUrl: string = HttpConfig.baseURL + 'banner/json';
13 | static readonly articleTopUrl: string = HttpConfig.baseURL + 'article/top/json';
14 | static readonly articleListUrl: string = HttpConfig.baseURL + 'article/list'; // /0/json
15 |
16 | //2-导航
17 | static readonly treeUrl: string = HttpConfig.baseURL + 'tree/json';
18 | static readonly treeListUrl: string = HttpConfig.baseURL + 'article/list';
19 |
20 | //3-项目
21 | static readonly projectUrl: string = HttpConfig.baseURL + 'project/tree/json';
22 | static readonly projectListUrl: string = HttpConfig.baseURL + 'project/list';
23 |
24 | //4-消息-需要登录
25 | static readonly msgUnreadUrl: string = HttpConfig.baseURL + 'message/lg/count_unread/json';
26 | static readonly msgReadUrl: string = HttpConfig.baseURL + 'message/lg/readed_list/'; //message/lg/readed_list/%s/json
27 |
28 | //5-用户信息
29 | static readonly userInfUrl: string = HttpConfig.baseURL + 'user/lg/userinfo/json';
30 |
31 | //6-登录、注册、退出
32 | static readonly loginUrl: string = HttpConfig.baseURL + 'user/login';
33 | static readonly registerUrl: string = HttpConfig.baseURL + 'user/register';
34 | static readonly logoutUrl: string = HttpConfig.baseURL + 'user/logout/json';
35 |
36 | //7-排行榜、积分
37 | static readonly rankUrl: string = HttpConfig.baseURL + 'coin/rank/'; //coin/rank/1/json
38 | static readonly coinUrl: string = HttpConfig.baseURL + 'lg/coin/list/'; //lg/coin/list/1/json
39 | /**
40 | * The request success status code.
41 | */
42 | static readonly SERVER_CODE_SUCCESS: number = 0;
43 |
44 | /**
45 | * The off set coefficient.
46 | */
47 | static readonly Y_OFF_SET_COEFFICIENT: number = 0.1;
48 |
49 | /**
50 | * The page size.
51 | */
52 | static readonly PAGE_SIZE: number = 10;
53 |
54 | /**
55 | * The refresh and load height.
56 | */
57 | static readonly CUSTOM_LAYOUT_HEIGHT: number = 70;
58 |
59 | /**
60 | * Gt tab data current page.
61 | */
62 | static readonly GET_TAB_DATA_CURRENT_PAGE: number = 1;
63 |
64 | /**
65 | * Http request success status code.
66 | */
67 | static readonly HTTP_CODE_200: number = 200;
68 | static readonly HTTP_CODE_0: number = 0;
69 | /**
70 | * The animation delay time.
71 | */
72 | static readonly DELAY_ANIMATION_DURATION: number = 300;
73 |
74 | /**
75 | * The delay time.
76 | */
77 | static readonly DELAY_TIME: number = 1000;
78 |
79 | /**
80 | * The animation duration.
81 | */
82 | static readonly ANIMATION_DURATION: number = 2000;
83 |
84 | /**
85 | * The http timeout duration.
86 | */
87 | static readonly HTTP_READ_TIMEOUT: number = 10000;
88 |
89 | /**
90 | * Content maxLine.
91 | */
92 | static readonly CONTENT_MAX_LINE: number = 3;
93 |
94 | /**
95 | * List space.
96 | */
97 | static readonly LIST_SPACE: number = 12;
98 |
99 | /**
100 | * Item img space.
101 | */
102 | static readonly ITEM_IMG_SPACE: number = 8;
103 |
104 | /**
105 | * Type font weight.
106 | */
107 | static readonly TYPE_FONT_WEIGHT: number = 700;
108 |
109 | /**
110 | * Title font weight.
111 | */
112 | static readonly TITLE_FONT_WEIGHT: number = 500;
113 |
114 | /**
115 | * Desc font weight.
116 | */
117 | static readonly DESC_FONT_WEIGHT: number = 400;
118 |
119 | /**
120 | * Type aspect ratio.
121 | */
122 | static readonly TYPE_ASPECT_RATIO: number = 2;
123 |
124 | /**
125 | * Desc opacity.
126 | */
127 | static readonly DESC_OPACITY: number = 0.6;
128 |
129 | /**
130 | * 100 percent.
131 | */
132 | static readonly FULL_PERCENT: string = '100%';
133 |
134 | /**
135 | * Divider width.
136 | */
137 | static readonly DIVIDER_WIDTH: string = '90%';
138 |
139 | /**
140 | * Release title.
141 | */
142 | static readonly RELEASE_TITLE: string = '新闻发布';
143 | }
144 |
145 | /**
146 | * The RefreshConstant constants.
147 | */
148 | export const enum RefreshConstant {
149 | DELAY_PULL_DOWN_REFRESH = 50,
150 | CLOSE_PULL_DOWN_REFRESH_TIME = 150,
151 | DELAY_SHRINK_ANIMATION_TIME = 500
152 | }
153 |
154 | /**
155 | * The refresh state enum.
156 | */
157 | export const enum RefreshState {
158 | DropDown = 0,
159 | Release = 1,
160 | Refreshing = 2,
161 | Success = 3,
162 | Fail = 4
163 | }
164 |
165 | /**
166 | * The newsList state enum.
167 | */
168 | export const enum PageState {
169 | Loading = 0,
170 | Success = 1,
171 | Fail = 2
172 | }
173 |
174 | /**
175 | * The file upload state enum.
176 | */
177 | export const enum UploadingState {
178 | COMPLETE = 'complete',
179 | FAIL = 'fail'
180 | }
181 |
182 | /**
183 | * The request method enum.
184 | */
185 | export const enum RequestMethod {
186 | POST = 'POST',
187 | GET = 'GET'
188 | }
189 |
190 | /**
191 | * The request content type enum.
192 | */
193 | export const enum ContentType {
194 | JSON = 'application/json',
195 | FORM = 'multipart/form-data',
196 | FORM_URLENCODED = 'application/x-www-form-urlencoded'
197 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/api/HttpRequest.ets:
--------------------------------------------------------------------------------
1 | import HttpConfig from './HttpConfig';
2 | import { httpRequestGet, httpRequestPost } from './HttpService';
3 | import ResponseResult from './ResponseResult';
4 |
5 | /**
6 | * @desc:Http网络请求
7 | */
8 |
9 | //1-home(首页)
10 | const bannerReq = ():Promise => httpRequestGet(HttpConfig.bannerUrl);
11 | const articleTopReq = ():Promise => httpRequestGet(HttpConfig.articleTopUrl);
12 | const articleListReq = (page: number):Promise => httpRequestGet(`${HttpConfig.articleListUrl}/${page}/json`);
13 |
14 | //2-nav(导航)
15 | const treeReq = ():Promise => httpRequestGet(HttpConfig.treeUrl);
16 | const treeListReq = (page: number, cid: number):Promise => httpRequestGet(`${HttpConfig.treeListUrl}/${page}/json?cid=${cid}`);
17 |
18 | //3-project(项目)
19 | const projectReq = ():Promise => httpRequestGet(HttpConfig.projectUrl);
20 | const projectListReq = (page: number, cid: number):Promise => httpRequestGet(`${HttpConfig.projectListUrl}/${page}/json?cid=${cid}`);
21 |
22 | //4-msg(消息)
23 | const msgUnReadReq = ():Promise =>httpRequestGet(HttpConfig.msgUnreadUrl);
24 | const msgReadReq = (page: number):Promise=>httpRequestGet(`${HttpConfig.msgReadUrl}/${page}/json`);
25 |
26 | //5-me(我的)
27 |
28 | const userReq = ():Promise => httpRequestGet(HttpConfig.userInfUrl);
29 |
30 |
31 | //6-login(登录)、register(注册)
32 | const loginReq = (username:string,password:string):Promise =>httpRequestPost(`${HttpConfig.loginUrl}?username=${username}&password=${password}`,Object({'username':username,"password":password}));
33 | const registerReq = (username:string,password:string,repassword:string):Promise =>httpRequestPost(`${HttpConfig.registerUrl}?username=${username}&password=${password}&repassword=${repassword}`,Object({'username':username,'password':password,'repassword':repassword}));
34 | const logoutReq = ():Promise => httpRequestGet(HttpConfig.logoutUrl);
35 |
36 | //7-排行榜(rank)、积分(coin-需登录)
37 | const rankReq = (page: number):Promise=>httpRequestGet(`${HttpConfig.rankUrl}/${page}/json`);
38 | const coinReq = (page: number):Promise=>httpRequestGet(`${HttpConfig.coinUrl}/${page}/json`);
39 |
40 | export {
41 | bannerReq, articleTopReq, articleListReq,
42 | treeReq,treeListReq,
43 | projectReq,projectListReq,
44 | msgUnReadReq,msgReadReq,
45 | userReq,
46 | loginReq,registerReq,logoutReq,
47 | rankReq,coinReq
48 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/api/HttpService.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | * @desc:网络请求工具类
15 | */
16 |
17 | import http from '@ohos.net.http';
18 | import ResponseResult from './ResponseResult';
19 | import HttpConfig, { ContentType } from './HttpConfig';
20 | import Constants from '../common/constants/Constants';
21 | import preferences from '@ohos.data.preferences';
22 | import * as Utils from "../utils/Utils";
23 | import PreferencesUtils from '../utils/PreferencesUtils';
24 | PersistentStorage.PersistProp(Constants.Cookie, '');
25 | /**
26 | * Initiate an HTTP GET request to the specified URL.
27 | *
28 | * @param url URL for initiating an HTTP request.
29 | */
30 | export function httpRequestGet(url: string) {
31 | return httpRequest(url, http.RequestMethod.GET);
32 | }
33 |
34 | /**
35 | * Initiate an HTTP POST request to the specified URL.
36 | *
37 | * @param url URL for initiating an HTTP request
38 | * @param newsData Additional data of the request
39 | * @returns
40 | */
41 | export function httpRequestPost(url: string, params: Object) {
42 | return httpRequest(url, http.RequestMethod.POST, params);
43 | }
44 |
45 | /**
46 | * Initiates an HTTP request to a given URL.
47 | *
48 | * @param url URL for initiating an HTTP request
49 | * @param method Request method.
50 | * @param extraData Additional data of the request.
51 | * @returns Returns {@link ResponseResult}.
52 | * @desc:说明:玩安卓官网的post请求使用extraData传递数据时,后台无法收到,故使用拼接的方式。其他平台的接口extraData可以传递数据。具体原因待研究
53 | */
54 |
55 |
56 | function httpRequest(url: string, method: http.RequestMethod, params?: object): Promise {
57 |
58 | let httpRequest = http.createHttp();
59 | let cookie1 = 'loginUserName_wanandroid_com=12345678;token_pass=08937b953a34ae42f65e461149b23129';
60 | let cookie3 = 'loginUserName_wanandroid_com=12345678;token_pass_wanandroid_com=08937b953a34ae42f65e461149b23129; Domain=wanandroid.com; Expires=Mon, 18-Dec-2023 08:20:48 GMT; Path=/'
61 | let cookie2 = 'loginUserName_wanandroid_com=12345678; token_pass_wanandroid_com=08937b953a34ae42f65e461149b23129; JSESSIONID=08D694B58BA92A81B0FA4648A9AA8E6E; loginUserName=12345678; token_pass=08937b953a34ae42f65e461149b23129';
62 | let cookie = PreferencesUtils.getStringData(Constants.Cookie)
63 | httpRequest.on('headersReceive', (header) => {
64 | //header['set-cookie'] = cookie;
65 | //header['Cookie'] = PreferencesUtils.getStringData(Constants.Cookie)
66 | //console.info('header: ' + JSON.stringify(header));
67 | });
68 |
69 | let responseResult = httpRequest.request(url, {
70 | method: method,
71 | extraData: params,
72 | //header: { 'Content-Type': method === http.RequestMethod.POST ? ContentType.FORM_URLENCODED : ContentType.JSON },
73 | header: {
74 | 'Content-Type': ContentType.JSON,
75 | //'Cookie': PreferencesUtils.getStringData(Constants.Cookie),
76 | //'Cookie': cookie,
77 | 'Cookie': AppStorage. Get(Constants.Cookie),
78 | },
79 | readTimeout: HttpConfig.HTTP_READ_TIMEOUT,
80 | connectTimeout: HttpConfig.HTTP_READ_TIMEOUT,
81 | });
82 | let serverData = new ResponseResult();
83 |
84 | // Processes the data and returns.
85 | return responseResult.then((value: http.HttpResponse) => {
86 | if (value.responseCode === HttpConfig.HTTP_CODE_200) {
87 | // Obtains the returned data.
88 | let result = `${value.result}`;
89 | if (url.includes("login") && !Utils.isEmpty(value.header['set-cookie']) || url.includes("register") && !Utils.isEmpty(value.header['set-cookie'])) {
90 | AppStorage.Set(Constants.Cookie, `loginUserName_wanandroid_com=${params?['username']:''};` + value.header['set-cookie'])
91 | //AppStorage.SetOrCreate('Cookie', `loginUserName_wanandroid_com=${params['username']};` + value.header['set-cookie'])
92 | //PersistentStorage.PersistProp('Cookie', `loginUserName_wanandroid_com=${params['username']};`+value.header['set-cookie']);
93 | //PreferencesUtils.putStringData(Constants.Cookie, `loginUserName_wanandroid_com=${params['username']};`+value.header['set-cookie'])
94 | }
95 | let resultJson: ResponseResult = JSON.parse(result);
96 | if (resultJson.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
97 | serverData.data = resultJson.data;
98 | }
99 | serverData.errorCode = resultJson.errorCode;
100 | serverData.errorMsg = resultJson.errorMsg;
101 | } else {
102 | serverData.errorMsg = `${$r('app.string.http_error_message')}&${value.responseCode}`;
103 | }
104 | return serverData;
105 | }).catch(() => {
106 | serverData.errorMsg = $r('app.string.http_error_message');
107 | return serverData;
108 | });
109 | }
110 |
--------------------------------------------------------------------------------
/entry/src/main/ets/api/ResponseResult.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:网络请求返回结果
3 | */
4 | export default class ResponseResult {
5 | /**
6 | * Code returned by the network request: success, fail.
7 | */
8 | errorCode: number;
9 |
10 | /**
11 | * Message returned by the network request.
12 | */
13 | errorMsg: string | Resource;
14 |
15 | /**
16 | * Data returned by the network request.
17 | */
18 | data: string | Object | ArrayBuffer;
19 |
20 | constructor() {
21 | this.errorCode = 0;
22 | this.errorMsg = '';
23 | this.data = '';
24 | }
25 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/ArticleBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:1-首页-置顶文章/列表文章
3 | */
4 | //置顶文章
5 | export class ArticleTop {
6 | data: Article[] = [];
7 | }
8 |
9 | //文章列表
10 | export class ArticleList {
11 | curPage: number = 0;
12 | datas: Article[] = [];
13 | offset: number = 0;
14 | over: boolean = false;
15 | pageCount: number = 0;
16 | size: number = 0;
17 | total: number = 0;
18 | }
19 |
20 |
21 | export class Article {
22 | isTop:boolean = false; //是否为置顶
23 | adminAdd: boolean = false; //是否为管理员添加
24 | apkLink: string = ''; //apk链接
25 | audit: number = 0;
26 | author: string = ''; //作者
27 | canEdit: boolean = false;
28 | chapterId: number = 0;
29 | chapterName: string = ''; //chapter
30 | collect: boolean = false;
31 | courseId: number = 0;
32 | desc: string = '';
33 | descMd: string = '';
34 | envelopePic: string = '';
35 | fresh: boolean = false;
36 | host: string = '';
37 | id: number = 0;
38 | isAdminAdd: boolean = false;
39 | link: string = '';
40 | niceDate: string = '';
41 | niceShareDate: string = '';
42 | origin: string = '';
43 | prefix: string = '';
44 | projectLink: string = '';
45 | publishTime: number = 0;
46 | realSuperChapterId: number = 0;
47 | selfVisible: number = 0;
48 | shareDate: number = 0;
49 | shareUser: number = 0;
50 | superChapterId: number = 0;
51 | superChapterName: string = '';
52 | tags: Tag[] = [];
53 | title: string = '';
54 | type: number = 0;
55 | userId: number = 0;
56 | visible: number = 0;
57 | zan: number = 0;
58 | }
59 |
60 | export class Tag {
61 | name: string = '';
62 | url: string = '';
63 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/BannerBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:1-首页-轮播图
3 | */
4 |
5 | export class Banner {
6 | desc: string = ''; //描述
7 | id: number = 0; //id
8 | imagePath: string = ''; //图片地址
9 | isVisible: number = 0; //是否可见
10 | order: number = 0;
11 | title: string = ''; //标题
12 | type: number = 0; //type类型
13 | url: string = ''; //文章地址
14 | }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/CoinBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * 积分排行-数据类
3 | */
4 |
5 | export class CoinData {
6 | curPage: number = 0;
7 | datas: CoinItem[] = [];
8 | offset: number = 0;
9 | over: boolean = false;
10 | pageCount: number = 0;
11 | size: number = 0;
12 | total: number = 0;
13 | }
14 |
15 |
16 | export class CoinItem {
17 | coinCount: number = 0;
18 | date: number = 0;
19 | desc: string = '';
20 | id: number = 0;
21 | reason: string = '';
22 | type: number = 0;
23 | userId: number = 0;
24 | username: string = '';
25 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/MsgBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:4-消息
3 | */
4 |
5 | export class MsgData {
6 | curPage: number = 0;
7 | datas: MsgItem[] = [];
8 | offset: number = 0;
9 | over: boolean = false;
10 | pageCount: number = 0;
11 | size: number = 0;
12 | total: number = 0;
13 | }
14 |
15 | export class MsgItem {
16 | category: number = 0;
17 | date: number = 0;
18 | fromUser: string = ''; //作者
19 | fromUserId: number = 0;
20 | fullLink: string = ''; //链接
21 | id: number = 0;
22 | isRead: number = 0;
23 | link: string = '';
24 | message: string = ''; //消息内容
25 | niceDate: string = ''; //日期
26 | tag: string = ''; //标签
27 | title: string = ''; //标题
28 | userId: number = 0;
29 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/ProjectBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:4-项目
3 | */
4 |
5 | export class ProjectData {
6 | data: ProjectItem[] = [];
7 | }
8 |
9 | export class ProjectItem {
10 | articleList: [] = [];
11 | author: string = '';
12 | children: ProjectItem[] = [];
13 | courseId: number = 0;
14 | cover: string = '';
15 | desc: string = '';
16 | id: number = 0;
17 | lisense: string = '';
18 | lisenseLink: string = '';
19 | name: string = ''; //显示的tab标题名字
20 | order: number = 0;
21 | parentChapterId: number = 0;
22 | type: number = 0;
23 | userControlSetTop: boolean = false;
24 | visible: number = 0;
25 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/RankBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * 积分排行-数据类
3 | */
4 |
5 | export class RankData {
6 | curPage: number = 0;
7 | datas: RankItem[] = [];
8 | offset: number = 0;
9 | over: boolean = false;
10 | pageCount: number = 0;
11 | size: number = 0;
12 | total: number = 0;
13 | }
14 |
15 |
16 | export class RankItem {
17 | coinCount: number = 0;
18 | level: number = 0;
19 | nickname: string = '';
20 | rank: string = '';
21 | userId: number = 0;
22 | username: string = '';
23 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/SettingItem.ets:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * List item data entity.
5 | */
6 | export default class PageResource {
7 | /**
8 | * Text of list item.
9 | */
10 | title: Resource;
11 | /**
12 | * Image of list item.
13 | */
14 | img: Resource;
15 | /**
16 | * Other resource of list item.
17 | */
18 | others?: Resource;
19 |
20 | constructor(title: Resource, img: Resource, others?: Resource) {
21 | this.title = title;
22 | this.img = img;
23 | this.others = others;
24 | }
25 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/TreeBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:2-Tree(导航)-数据类
3 | */
4 | import { Article } from './ArticleBean';
5 |
6 | //体系数据
7 | export class TreeData {
8 | data: TreeItem[] = [];
9 | }
10 |
11 | export class TreeItem {
12 | articleList: [] = [];
13 | author: string = '';
14 | children: TreeItem[] = [];
15 | courseId: number = 0;
16 | cover: string = '';
17 | desc: string = '';
18 | id: number = 0;
19 | lisense: string = '';
20 | lisenseLink: string = '';
21 | name: string = '';
22 | order: number = 0;
23 | parentChapterId: number = 0;
24 | type: number = 0;
25 | userControlSetTop: boolean = false;
26 | visible: number = 0;
27 | }
28 | //知识体系下的文章
29 | export class TreeArticle {
30 | curPage: number = 1;
31 | offset: number = 0;
32 | over: boolean = false;
33 | pageCount: number = 0;
34 | size: number = 0;
35 | total: number = 0;
36 | datas: Article[] = [];
37 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/bean/UserInfoBean.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:5-用户数据
3 | */
4 |
5 | export class UserData {
6 | coinInfo: CoinInfo = new CoinInfo();
7 | userInfo: UserInfo = new UserInfo()
8 | }
9 |
10 | export class UserInfo {
11 | admin: boolean = false;
12 | chapterTops: [] = [];
13 | coinCount: number = 0;
14 | collectIds: [] = [];
15 | email: string = '';
16 | icon: string = '';
17 | id: number = 0;
18 | nickname: string = '';
19 | password: string = '';
20 | publicName: string = '';
21 | token: string = '';
22 | type: number = 0;
23 | username: string = '';
24 | }
25 |
26 | export class CoinInfo {
27 | coinCount: number = 0; // 可用
28 | level: number = 0; // 可用
29 | nickname: string = '';
30 | rank: string = ''; // 可用
31 | userId: number = 0; // 可用
32 | username: string = '';
33 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/common/bean/BottomTabsItem.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | /**
17 | * Interface of bottom tab item.
18 | */
19 | export interface BottomTabsItem {
20 | icon: Resource;
21 | iconSelected: Resource;
22 | text: Resource;
23 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/common/constants/Constants.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:定义常量
3 | */
4 | import SettingItem from '../../bean/SettingItem';
5 |
6 | export default class Constants {
7 |
8 | /**
9 | * route path
10 | */
11 | static readonly Splash_Path: string = 'pages/Splash';
12 | static readonly MainPage_Path: string = 'pages/MainPage';
13 | static readonly LoginRegister_Path: string = 'pages/LoginRegisterPage';
14 | static readonly WebPage_Path: string = 'pages/WebPage';
15 | static readonly SettingPage_Path: string = 'pages/SettingPage';
16 | static readonly TreeTabPage_Path: string = 'pages/TreeTabPage';
17 | static readonly InfoPage_Path: string = 'pages/InfoPage';
18 |
19 |
20 | /**
21 | * Component size.
22 | */
23 | static readonly ICON_SIZE: string = '40%';
24 | static readonly FULL_PERCENT: string = '100%';
25 | static readonly BAR_HEIGHT: string = '10%';
26 | static readonly FULL_SIZE: string = '100%';
27 |
28 |
29 | /**
30 | * Component location.
31 | */
32 | static readonly PERCENTAGE_15: string = '15%';
33 | static readonly PERCENTAGE_25: string = '25%';
34 | /**
35 | * Component constants.
36 | */
37 | static readonly OPACITY: number = 0.6;
38 | static readonly BORDER_WIDTH: number = 0.5;
39 |
40 | /**
41 | * BottomTabIndex
42 | */
43 | static readonly HOME_TAB_INDEX = 0;
44 | static readonly NAV_TAB_INDEX = 1;
45 | static readonly PROJECT_TAB_INDEX = 2;
46 | static readonly MSG_TAB_INDEX = 3;
47 | static readonly MINE_TAB_INDEX = 4;
48 |
49 |
50 | /**
51 | * WebView
52 | */
53 | static readonly WebConstant_PROGRESS_MAX: number = 100;
54 | static readonly WebConstant_PROGRESS_MIN: number = 0;
55 | static readonly WebConstant_PROGRESS_STEP: number = 10;
56 | static readonly WebConstant_MILLI_SECONDS: number = 100;
57 | static readonly WebConstant_DURATION: number = 3000;
58 | static readonly WebConstant_PROGRESS_WIDTH: number = 80;
59 | static readonly WebConstant_PROGRESS_STROKE_WIDTH: number = 15;
60 | static readonly WebConstant_PROGRESS_SCALE_COUNT: number = 15;
61 | static readonly WebConstant_PROGRESS_SCALE_WIDTH: number = 5;
62 | static readonly WebConstant_PROGRESS_POSITION_X: string = '40%';
63 | static readonly WebConstant_PROGRESS_POSITION_Y: string = '40%';
64 | /**
65 | * The width or height of the component is spread across the parent component.
66 | */
67 | static readonly FULL_PARENT = '100%';
68 |
69 | /**
70 | * Shared transition duration.
71 | */
72 | static readonly SHARED_DURATION: number = 800;
73 | /**
74 | * Page transition exit delay.
75 | */
76 | static readonly EXIT_DELAY: number = 100;
77 | /**
78 | * Type font weight.
79 | */
80 | static readonly TYPE_FONT_WEIGHT: number = 700;
81 | /**
82 | * Desc font weight.
83 | */
84 | static readonly DESC_FONT_WEIGHT: number = 400;
85 | /**
86 | * Left padding of the input box
87 | */
88 | static readonly INPUT_PADDING_LEFT = 0;
89 | /**
90 | * Delay time of simulated login
91 | */
92 | static readonly LOGIN_DELAY_TIME = 2000;
93 | /**
94 | * Input length of the account.
95 | */
96 | static readonly INPUT_ACCOUNT_LENGTH = 16;
97 | /**
98 | * Input length of the password.
99 | */
100 | static readonly INPUT_PASSWORD_LENGTH = 16;
101 | /**
102 | * The width of button
103 | */
104 | static readonly BUTTON_WIDTH = '90%';
105 | static readonly SET_LIST_WIDTH = '42%';
106 |
107 | /**
108 | * 常量
109 | */
110 | static readonly RANK = 'rank';
111 | static readonly COLLECT = 'collect';
112 | static readonly LEVEL = 'level';
113 | static readonly COIN = 'coin';
114 |
115 | /**
116 | * Preference-key
117 | */
118 | static readonly Cookie: string = 'cookie';
119 | static readonly settingListData: SettingItem[] = [
120 | new SettingItem($r('app.string.setting_list_theme'), $r('app.media.ic_theme'), $r(null)),
121 | new SettingItem($r('app.string.setting_list_language'), $r('app.media.ic_language'), $r(null)),
122 | new SettingItem($r('app.string.setting_list_about'), $r('app.media.ic_about'), $r(null)),
123 | ];
124 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/entryability/EntryAbility.ets:
--------------------------------------------------------------------------------
1 | import UIAbility from '@ohos.app.ability.UIAbility';
2 | import hilog from '@ohos.hilog';
3 | import window from '@ohos.window';
4 | import Constants from '../common/constants/Constants';
5 | import AbilityConstant from '@ohos.app.ability.AbilityConstant';
6 | import Want from '@ohos.app.ability.Want';
7 |
8 | export default class EntryAbility extends UIAbility {
9 | //api10版本
10 | onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
11 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
12 | globalThis.abilityContext = this.context;
13 | }
14 | //api9版本
15 | // onCreate(want, launchParam) {
16 | // hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
17 | // globalThis.abilityContext = this.context;
18 | // //初始化不要放在这里
19 | // // if (!AppStorage.Has(Constants.Cookie)) {
20 | // // PersistentStorage.PersistProp('Cookie', '');
21 | // // }
22 | // }
23 | //
24 |
25 | onDestroy() {
26 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
27 | }
28 |
29 | onWindowStageCreate(windowStage: window.WindowStage) {
30 | // Main window is created, set main page for this ability
31 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
32 |
33 | windowStage.loadContent(Constants.Splash_Path, (err, data) => {
34 | if (err.code) {
35 | hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
36 | return;
37 | }
38 | hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
39 | });
40 | }
41 |
42 | onWindowStageDestroy() {
43 | // Main window is destroyed, release UI related resources
44 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
45 | }
46 |
47 | onForeground() {
48 | // Ability has brought to foreground
49 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
50 | }
51 |
52 | onBackground() {
53 | // Ability has back to background
54 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/HomePage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import { Article, ArticleList, ArticleTop } from '../bean/ArticleBean';
3 | import { Banner } from '../bean/BannerBean';
4 | import ArticleItem from '../view/ArticleItem';
5 | import HomeViewModel from '../viewmodel/HomeViewModel';
6 | import { NavigatorModel } from '../viewmodel/NavigatorModel';
7 | import { PullToRefresh } from '@ohos/pulltorefresh'
8 | import * as Utils from "../utils/Utils";
9 | import prompt from '@ohos.promptAction';
10 | import Constants from '../common/constants/Constants';
11 |
12 | /**
13 | * @desc:1-首页
14 | */
15 | @Preview
16 | @Component
17 | export default struct HomePage {
18 | private swiperController: SwiperController = new SwiperController();
19 | @State bannerData: Banner[] = [];
20 | @State articleTopData: Article[] = [];
21 | @State articleListData: ArticleList = new ArticleList()
22 | @State articleData: Article[] = [];
23 | @State pageNum: number = 0; //分页page
24 | private scroller: Scroller = new Scroller(); // 需绑定列表或宫格组件
25 |
26 | //页面即将显示时
27 | async aboutToAppear() {
28 | //1-首页全部接口数据
29 | this.getHomeBannerData()
30 | //2-首页-文章接口数据
31 | //this.getHomeArticleListData(0)
32 | }
33 |
34 | //1-首页全部接口数据
35 | getHomeBannerData() {
36 | //1-首页全部接口数据
37 | HomeViewModel.getHomeData().then(result => {
38 | this.bannerData = result[0] as Banner[]
39 | this.articleTopData = (result[1] as Article[])
40 | this.articleTopData.forEach(item => {
41 | item.isTop = true
42 | })
43 | this.articleListData = result[2]
44 |
45 | this.articleData = [...this.articleTopData, ...this.articleListData.datas]
46 | console.log("result")
47 | })
48 | }
49 |
50 | //2-首页-文章接口数据
51 | getHomeArticleListData(page: number) {
52 | //2-首页-文章接口数据
53 | HomeViewModel.getArticle(page).then(result => {
54 | this.articleData.push(...result.datas)
55 | // result.datas.forEach((article, index) => {
56 | // console.log('article>>>', article)
57 | // this.articleData.push(article)
58 | // })
59 | console.log('article>>>', JSON.stringify(result))
60 | })
61 | }
62 |
63 | @Builder
64 | private homeListView() {
65 | //Article
66 | List({ scroller: this.scroller }) {
67 | //Banner轮播图
68 | ListItem() {
69 | if (this.bannerData.length > 0) {
70 | Swiper(this.swiperController) {
71 | ForEach(this.bannerData, (banner: Banner) => {
72 | Navigator({ target: Constants.WebPage_Path, type: NavigationType.Push }) {
73 | Image(banner.imagePath)
74 | }.params({ path: banner.url, title: banner.title } as NavigatorModel)
75 | }, (img: Resource) => JSON.stringify(img.id))
76 | }.height(200).width('100%')
77 | .autoPlay(true)
78 | }
79 | }
80 |
81 | //文章条目
82 | ForEach(this.articleData, (article: Article) => {
83 | ListItem() {
84 | Navigator({ target: Constants.WebPage_Path, type: NavigationType.Push }) {
85 | ArticleItem({ article: article })
86 | }.params({ path: article.link, title: article.title } as NavigatorModel)
87 | }
88 | })
89 | }
90 | .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果
91 | }
92 |
93 | build() {
94 | Column() {
95 | PullToRefresh({
96 | data: this.articleData,
97 | scroller: this.scroller,
98 | customList: () => this.homeListView(),
99 | onRefresh: () => {
100 | return new Promise((resolve, reject) => {
101 | setTimeout(() => {
102 | resolve('刷新成功');
103 | this.pageNum = 0;
104 | this.articleData.forEach((item, index) => {
105 | this.articleData.pop()
106 | })
107 | this.getHomeArticleListData(this.pageNum)
108 | }, 1000);
109 | });
110 | },
111 | onLoadMore: () => {
112 | return new Promise((resolve, reject) => {
113 | setTimeout(() => {
114 | resolve('onLoadMore');
115 | if (!this.articleListData.over) {
116 | this.getHomeArticleListData(++this.pageNum)
117 | } else {
118 | prompt.showToast({ message: $r('app.string.no_more_data') })
119 | }
120 | }, 1000);
121 | });
122 | },
123 | customLoad: null,
124 | customRefresh: null,
125 | })
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/InfoPage.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * 积分排行或个人积分页面
3 | */
4 | import router from '@ohos.router';
5 | import { CoinData, CoinItem } from '../bean/CoinBean';
6 | import { RankData, RankItem } from '../bean/RankBean';
7 | import Constants from '../common/constants/Constants';
8 | import InfoItem from '../view/InfoItem';
9 | import TitleBar from '../view/TitleBar'
10 | import InfoViewModel from '../viewmodel/InfoViewModel';
11 |
12 | @Preview
13 | @Entry
14 | @Component
15 | struct InfoPage {
16 | @State params: object = router.getParams();
17 | @State title: string = '';
18 | //积分数据
19 | @State coinData: CoinData = new CoinData;
20 | @State coinListData: CoinItem[] = [];
21 | //排行榜数据
22 | @State rankData: RankData = new RankData;
23 | @State rankListData: RankItem[] = [];
24 |
25 | aboutToAppear() {
26 | switch (this.params['title']) {
27 | case Constants.RANK:
28 | this.title = '积分排行榜';
29 | this.getRankData(1)
30 |
31 | break;
32 | case Constants.COIN:
33 | this.title = '个人积分列表';
34 | this.getCoinData(1)
35 | break;
36 | default:
37 | this.title = '其他';
38 | break;
39 | }
40 | }
41 |
42 | getRankData(page: number) {
43 | InfoViewModel.getRank(1).then((rankData: RankData) => {
44 | this.rankData = rankData;
45 | this.rankListData = rankData.datas
46 | })
47 | }
48 |
49 | getCoinData(page: number) {
50 | InfoViewModel.getCoin(1).then((coinData: CoinData) => {
51 | this.coinData = coinData;
52 | this.coinListData = coinData.datas;
53 | })
54 | }
55 |
56 | @Builder
57 | listRank() {
58 | List({ space: 10 }) {
59 | ForEach(this.rankListData, (item: RankItem, index) => {
60 | ListItem() {
61 | InfoItem({
62 | param1: `排名:${item.rank}`,
63 | param2: `用户名:${item.username}`,
64 | param3: `用户等级:${item.level}`,
65 | param4: `用户积分:${item.coinCount}`,
66 | })
67 | }
68 | })
69 | }
70 | }
71 |
72 | @Builder
73 | listCoin() {
74 | List({ space: 10 }) {
75 | ForEach(this.coinListData, (item: CoinItem, index) => {
76 | ListItem() {
77 | InfoItem({
78 | param1: `类型:${item.reason}`,
79 | param2: `获得积分:${item.coinCount}`,
80 | param3: `用户等级:${item.desc}`,
81 | })
82 | }
83 | })
84 | }
85 | }
86 |
87 | build() {
88 | Column() {
89 | //1-头部
90 | TitleBar({ title: this.title })
91 | if (this.params['title'] === Constants.RANK) {
92 | this.listRank()
93 | } else if (this.params['title'] === Constants.COIN) {
94 | this.listCoin()
95 | }
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/LoginRegisterPage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import router from '@ohos.router';
3 | import prompt from '@ohos.promptAction';
4 | import Constants from '../common/constants/Constants';
5 | import LoginRegisterViewModel from '../viewmodel/LoginRegisterViewModel';
6 | import { UserInfo } from '../bean/UserInfoBean';
7 | import * as Utils from "../utils/Utils";
8 | import ResponseResult from '../api/ResponseResult';
9 | /**
10 | * @desc: 6-登录注册页面
11 | */
12 |
13 | @Extend(TextInput) function inputStyle() {
14 | .placeholderColor($r('app.color.gray'))
15 | .height($r('app.float.45vp'))
16 | .fontSize($r('app.float.18fp'))
17 | .backgroundColor($r('app.color.snow'))
18 | .width(Constants.FULL_PARENT)
19 | .padding({ left: Constants.INPUT_PADDING_LEFT })
20 | .margin({ top: $r('app.float.12vp') })
21 | }
22 |
23 | @Extend(Line) function lineStyle() {
24 | .width(Constants.FULL_PARENT)
25 | .height($r('app.float.1vp'))
26 | .backgroundColor($r('app.color.gray'))
27 | }
28 |
29 | @Extend(Text) function blueTextStyle() {
30 | .fontColor($r('app.color.dodger_blue'))
31 | .fontSize($r('app.float.14fp'))
32 | .fontWeight(FontWeight.Medium)
33 | }
34 |
35 | @Preview
36 | @Entry
37 | @Component
38 | export default struct LoginRegisterPage {
39 | @State username: string = '';
40 | @State password: string = '';
41 | @State repassword: string = '';
42 | @State isRegister: boolean = false;
43 | @State isShowProgress: boolean = false;
44 | private timeOutId: number = -1;
45 |
46 | @Builder
47 | imageButton(src: Resource) {
48 | Button({ type: ButtonType.Circle, stateEffect: true }) {
49 | Image(src)
50 | }
51 | .height($r('app.float.48vp'))
52 | .width($r('app.float.48vp'))
53 | .backgroundColor($r('app.color.snow'))
54 | }
55 |
56 | loginAndRegister(): void {
57 | this.isRegister ? this.register() : this.login()
58 | }
59 |
60 | login() {
61 | if (this.username === '' || this.password === '') {
62 | prompt.showToast({ message: $r('app.string.input_empty_tips') })
63 | } else {
64 | //处理登录逻辑
65 | this.isShowProgress = true;
66 | LoginRegisterViewModel.userLogin(this.username, this.password).then((result: ResponseResult) => {
67 | //console.log('UserInfo>>>', userInfo)
68 | console.log('result>>>', result)
69 | if (!Utils.isEmpty(result.data as UserInfo)) {
70 | this.delay()
71 | } else {
72 | this.isShowProgress = false;
73 | prompt.showToast({ message: result.errorMsg })
74 | }
75 | })
76 | }
77 | }
78 |
79 | register() {
80 | if (this.username === '' || this.password === '' || this.repassword === '') {
81 | prompt.showToast({ message: $r('app.string.input_empty_tips') })
82 | } else {
83 | //处理注册逻辑
84 | this.isShowProgress = true;
85 | LoginRegisterViewModel.userRegister(this.username, this.password, this.repassword).then(result => {
86 | console.log('UserInfo>>>', result)
87 | if (!Utils.isEmpty(result.data as UserInfo)) {
88 | this.delay()
89 | } else {
90 | this.isShowProgress = false;
91 | prompt.showToast({ message: result.errorMsg })
92 | }
93 | })
94 | }
95 | }
96 |
97 | //延迟加载
98 | delay() {
99 | if (this.timeOutId === -1) {
100 | this.timeOutId = setTimeout(() => {
101 | this.isShowProgress = false;
102 | this.timeOutId = -1;
103 | router.replaceUrl({ url: Constants.MainPage_Path });
104 | }, Constants.LOGIN_DELAY_TIME);
105 | }
106 | }
107 |
108 | aboutToDisappear() {
109 | clearTimeout(this.timeOutId);
110 | this.timeOutId = -1;
111 | }
112 |
113 | build() {
114 | Column() {
115 | Flex({ justifyContent: FlexAlign.Start }) {
116 | Image($r('app.media.ic_arrow_left'))
117 | .size({ width: $r('app.float.30vp'), height: $r('app.float.30vp') })
118 | .margin({ right: $r('app.float.10vp'), top: $r('app.float.10vp') })
119 | .onClick(() => {
120 | router.back()
121 | })
122 | }
123 |
124 | Image($r('app.media.ic_logo'))
125 | .width($r('app.float.70vp'))
126 | .height($r('app.float.70vp'))
127 | .margin({ top: $r('app.float.100vp'), bottom: $r('app.float.8vp') })
128 | Text(!this.isRegister ? $r('app.string.login_page') : $r('app.string.register_page'))
129 | .fontSize($r('app.float.24fp'))
130 | .fontWeight(FontWeight.Medium)
131 | .fontColor($r('app.color.black'))
132 | Text(!this.isRegister ? $r('app.string.login_more') : $r('app.string.register_more'))
133 | .fontSize($r('app.float.16fp'))
134 | .fontColor($r('app.color.gray'))
135 | .margin({ bottom: $r('app.float.30vp'), top: $r('app.float.8vp') })
136 |
137 | TextInput({ placeholder: $r('app.string.account'), text: this.username })
138 | .maxLength(Constants.INPUT_ACCOUNT_LENGTH)
139 | //.type(InputType.Normal)
140 | .inputStyle()
141 | .onChange((value: string) => {
142 | this.username = value;
143 | })
144 | Line().lineStyle()
145 |
146 | TextInput({ placeholder: $r('app.string.password'), text: this.password })
147 | .maxLength(Constants.INPUT_PASSWORD_LENGTH)
148 | .type(InputType.Password)
149 | .inputStyle()
150 | .onChange((value: string) => {
151 | this.password = value;
152 | })
153 | Line().lineStyle()
154 |
155 |
156 | //注册时-显示确认密码
157 | if (this.isRegister) {
158 | TextInput({ placeholder: $r('app.string.repassword'), text: this.repassword })
159 | .maxLength(Constants.INPUT_PASSWORD_LENGTH)
160 | .type(InputType.Password)
161 | .inputStyle()
162 | .onChange((value: string) => {
163 | this.repassword = value;
164 | })
165 | Line().lineStyle()
166 | }
167 |
168 | Button(!this.isRegister ? $r('app.string.login') : $r('app.string.register'), { type: ButtonType.Capsule })
169 | .width(Constants.BUTTON_WIDTH)
170 | .height($r('app.float.40vp'))
171 | .fontSize($r('app.float.16fp'))
172 | .fontWeight(FontWeight.Medium)
173 | .backgroundColor($r('app.color.dodger_blue'))
174 | .margin({ top: $r('app.float.87vp'), bottom: $r('app.float.12vp') })
175 | .onClick(() => {
176 | this.loginAndRegister();
177 | })
178 | Text(!this.isRegister ? $r('app.string.register_account') : $r('app.string.login_account'))
179 | .fontColor($r('app.color.dodger_blue'))
180 | .fontSize($r('app.float.16fp'))
181 | .fontWeight(FontWeight.Medium)
182 | .onFocus(() => {
183 |
184 | })
185 | .onClick(() => {
186 | this.isRegister = !this.isRegister
187 | this.username = ''
188 | this.password = ''
189 | this.repassword = ''
190 | })
191 |
192 | if (this.isShowProgress) {
193 | LoadingProgress()
194 | .color($r('app.color.slate_gray'))
195 | .width($r('app.float.30vp'))
196 | .height($r('app.float.30vp'))
197 | .margin({ top: $r('app.float.20vp') })
198 | }
199 |
200 | }
201 | .backgroundColor($r('app.color.snow'))
202 | .height(Constants.FULL_PARENT)
203 | .width(Constants.FULL_PARENT)
204 | .padding({
205 | left: $r('app.float.12vp'),
206 | right: $r('app.float.12vp'),
207 | bottom: $r('app.float.24vp')
208 | })
209 | }
210 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/MainPage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import Constants from '../common/constants/Constants';
3 | import { BottomTabsList } from '../viewmodel/BottomTabsModel';
4 | import HomePage from './HomePage';
5 | import MePage from './MePage';
6 | import MsgPage from './MsgPage';
7 | import TreePage from './TreePage';
8 | import ProjectPage from './ProjectPage';
9 |
10 | /**
11 | * @desc:主项目框架
12 | */
13 | @Preview
14 | @Entry
15 | @Component
16 | struct MainPage {
17 | @State bottomTabIndex: number = 0;
18 | private tabsController: TabsController = new TabsController();
19 |
20 | @Builder TabBuilder(index: number, _name: string) {
21 | Column() {
22 | Image(this.bottomTabIndex === index ? BottomTabsList[index].iconSelected : BottomTabsList[index].icon)
23 | .width(Constants.ICON_SIZE)
24 | .height(Constants.ICON_SIZE)
25 | .objectFit(ImageFit.Contain)
26 |
27 | Text(BottomTabsList[index].text)
28 | .fontSize($r('app.float.bottom_font_size'))
29 | .opacity(Constants.OPACITY)
30 | .fontColor(this.bottomTabIndex === index ?
31 | $r('app.color.bottom_tabs_font_color_selected') : $r('app.color.bottom_tabs_font_color'))
32 | }
33 | .width(Constants.FULL_PERCENT)
34 | .height(Constants.FULL_PERCENT)
35 | .justifyContent(FlexAlign.Center)
36 | .border({ width: { top: Constants.BORDER_WIDTH }, color: $r('app.color.color_border') })
37 | .backgroundColor($r('app.color.bottom_tabs_background_color'))
38 | }
39 |
40 | /**
41 | * In low-code mode, do not add anything to the build function, as it will be
42 | * overwritten by the content generated by the .visual file in the build phase.
43 | */
44 | build() {
45 | Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.End, justifyContent: FlexAlign.End }) {
46 | Tabs({ barPosition: BarPosition.End, index: 0, controller: this.tabsController }) {
47 | TabContent() {
48 | HomePage()
49 | }.tabBar(this.TabBuilder(0, 'Home'))
50 |
51 | TabContent() {
52 | TreePage()
53 | }.tabBar(this.TabBuilder(1, 'Nav'))
54 |
55 | TabContent() {
56 | ProjectPage()
57 | }.tabBar(this.TabBuilder(2, 'Project'))
58 |
59 | TabContent() {
60 | MsgPage()
61 | }.tabBar(this.TabBuilder(3, 'Msg'))
62 |
63 | TabContent() {
64 | MePage()
65 | }.tabBar(this.TabBuilder(4, 'Me'))
66 |
67 | }
68 | .width(Constants.FULL_PERCENT)
69 | .height(Constants.FULL_PERCENT)
70 | .vertical(false)
71 | .scrollable(false)
72 | .barMode(BarMode.Fixed)
73 | .barHeight(Constants.BAR_HEIGHT)
74 | .onChange((index: number) => {
75 | this.bottomTabIndex = index;
76 | })
77 | }
78 | .width(Constants.FULL_PERCENT)
79 | }
80 |
81 | onIndexChange() {
82 | this.tabsController.changeIndex(this.bottomTabIndex);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/MePage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import Constants from '../common/constants/Constants';
3 | import MineFunc from '../view/MineFunc';
4 | import MineHead from '../view/MineHead';
5 |
6 | /**
7 | * @desc:5-我的
8 | */
9 |
10 | @Preview
11 | @Component
12 | export default struct MePage {
13 | build() {
14 | Scroll() {
15 | Column() {
16 | MineHead() //我的-头部信息
17 | MineFunc() //我的-功能
18 | }
19 | .height(Constants.FULL_PERCENT)
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/MsgPage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import router from '@ohos.router';
3 | import MsgReadList from '../view/MsgReadList';
4 | import MsgUnreadList from '../view/MsgUnreadList';
5 | import MsgViewModel from '../viewmodel/MsgViewModel';
6 |
7 | /**
8 | * @desc:4-消息
9 | */
10 | @Preview
11 | @Component
12 | export default struct MsgPage {
13 | private tabsController: TabsController = new TabsController()
14 | @State currentIndex: number = 0;
15 |
16 | build() {
17 | Tabs({ barPosition: BarPosition.Start }) {
18 | TabContent() {
19 | MsgUnreadList()
20 | }
21 | .tabBar('未读消息')
22 |
23 | TabContent() {
24 | MsgReadList()
25 | }
26 | .tabBar('已读消息')
27 | }.onChange((index) => {
28 | this.currentIndex = index
29 | })
30 | }
31 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/ProjectPage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import router from '@ohos.router';
3 | import { ProjectItem } from '../bean/ProjectBean';
4 | import Constants from '../common/constants/Constants';
5 | import ProjectList from '../view/ProjectList';
6 | import ProjectViewModel from '../viewmodel/ProjectViewModel';
7 |
8 | /**
9 | * @desc:3-项目
10 | */
11 | @Preview
12 | @Component
13 | export default struct ProjectPage {
14 | @State projectData: ProjectItem[] = [];
15 | @State currentIndex: number = 0;
16 | @State optionsDic: Map = new Map();
17 | //页面即将显示时
18 | aboutToAppear() {
19 | //1-项目分类
20 | ProjectViewModel.getProject().then((result: ProjectItem[]) => {
21 | console.log('project>>>', result)
22 | this.projectData = result
23 | this.projectData.forEach((project, index) => {
24 | this.optionsDic[index] = project.id //将tab_index对应的cid放到map中
25 | })
26 | })
27 | }
28 |
29 | //自定义Tab
30 | @Builder TabBuilder(index: number) {
31 | Column() {
32 | Text(this.projectData[index].name)
33 | .height(Constants.FULL_PERCENT)
34 | .fontSize(this.currentIndex === index ? $r('app.float.24fp') : $r('app.float.18fp'))
35 | .fontWeight(this.currentIndex === index ? Constants.TYPE_FONT_WEIGHT : Constants.DESC_FONT_WEIGHT)
36 | .fontColor($r('app.color.black'))
37 | }
38 | .padding({ left: $r('app.float.8vp'), right: $r('app.float.8vp') })
39 | .margin({
40 | left: index === 0 ? $r('app.float.8vp') : 0,
41 | right: index === this.projectData.length - 1 ? $r('app.float.8vp') : 0
42 | })
43 | }
44 |
45 | build() {
46 | Tabs({ barPosition: BarPosition.Start }) {
47 | ForEach(this.projectData, (projectItem: ProjectItem, index?: number) => {
48 | TabContent() {
49 | ProjectList({ index, optionsDic: this.optionsDic, currentIndex: $currentIndex })
50 | }.tabBar(this.TabBuilder(index?index:0))
51 | }, (tabItem: ProjectItem) => JSON.stringify(tabItem))
52 | }
53 | .barHeight($r('app.float.50vp'))
54 | .height(Constants.FULL_PERCENT)
55 | .barMode(BarMode.Scrollable)
56 | .onChange((index: number) => {
57 | this.currentIndex = index;
58 | })
59 | .vertical(false)
60 | }
61 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/SettingPage.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:7-设置页面
3 | */
4 | import router from '@ohos.router'
5 | import SettingItem from '../bean/SettingItem'
6 | import Constants from '../common/constants/Constants'
7 | import TitleBar from '../view/TitleBar'
8 | import SettingViewModel from '../viewmodel/SettingViewModel'
9 |
10 | @Preview
11 | @Entry
12 | @Component
13 | export default struct SettingPage {
14 | @Builder settingCell(item: SettingItem) {
15 | Row() {
16 | Row({ space: 12 }) {
17 | Image(item.img)
18 | .width($r('app.float.22vp'))
19 | .height($r('app.float.22vp'))
20 | Text(item.title)
21 | .fontSize($r('app.float.16fp'))
22 | }
23 |
24 | if (item.others === null) {
25 | Image($r('app.media.ic_arrow_right'))
26 | .width($r('app.float.12vp'))
27 | .height($r('app.float.24vp'))
28 | } else {
29 | Toggle({ type: ToggleType.Switch, isOn: false })
30 | }
31 | }
32 | .justifyContent(FlexAlign.SpaceBetween)
33 | .width(Constants.FULL_PERCENT)
34 | .padding({
35 | left: $r('app.float.8vp'),
36 | right: $r('app.float.22vp')
37 | })
38 | }
39 |
40 | build() {
41 | Column() {
42 | //1-头部
43 | TitleBar({ title: '设置' })
44 | //2-设置
45 | List() {
46 | ForEach(SettingViewModel.getSettingListData(), (item: SettingItem) => {
47 | ListItem() {
48 | this.settingCell(item)
49 | }
50 | .height($r('app.float.48vp'))
51 | }, (item: SettingItem) => JSON.stringify(item))
52 | }
53 | .backgroundColor(Color.White)
54 | .width(Constants.FULL_PARENT)
55 | .height(Constants.SET_LIST_WIDTH)
56 | .divider({
57 | strokeWidth: $r('app.float.1vp'),
58 | color: Color.Grey,
59 | startMargin: $r('app.float.42vp'),
60 | endMargin: $r('app.float.24vp')
61 | })
62 | .borderRadius($r('app.float.16vp'))
63 | .padding({ top: $r('app.float.4vp'), bottom: $r('app.float.4vp') })
64 |
65 | //3-推出
66 |
67 | Button('退出登录', { type: ButtonType.Capsule })
68 | .width(Constants.BUTTON_WIDTH)
69 | .height($r('app.float.40vp'))
70 | .fontSize($r('app.float.16fp'))
71 | .fontColor($r('app.color.fire_brick'))
72 | .fontWeight(FontWeight.Medium)
73 | .backgroundColor($r('app.color.gainsboro'))
74 | .margin({ bottom: $r('app.float.50vp') })
75 | .onClick(() => {
76 | SettingViewModel.logout()
77 | })
78 |
79 | Blank()
80 |
81 | }
82 | .height(Constants.FULL_PARENT)
83 | }
84 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/Splash.ets:
--------------------------------------------------------------------------------
1 | import Constants from '../common/constants/Constants'
2 | import router from '@ohos.router';
3 | /**
4 | * @desc:启动页面
5 | *
6 | */
7 | @Entry
8 | @Component
9 | struct Splash {
10 | @State countdown: number = 2;
11 | private timer: number = -1;
12 |
13 | aboutToAppear(): void {
14 | setTimeout(() => {
15 | this.startTiming();
16 | }, 1000);
17 | }
18 |
19 | startTiming() {
20 | this.timer = setInterval(() => {
21 | this.countdown--;
22 | if (this.countdown === 0) {
23 | this.clearTiming();
24 | this.jumpToMainPage();
25 | }
26 | }, 1000);
27 | }
28 |
29 | clearTiming() {
30 | if (this.timer !== -1) {
31 | clearInterval(this.timer);
32 | this.timer = -1;
33 | }
34 | }
35 |
36 | jumpToMainPage() {
37 | this.clearTiming();
38 | router.replaceUrl({
39 | url: Constants.MainPage_Path
40 | });
41 | }
42 |
43 | aboutToDisappear() {
44 | this.clearTiming();
45 | }
46 |
47 | build() {
48 | Column() {
49 | Stack() {
50 | Image($r('app.media.splash_bg'))
51 | .width(Constants.FULL_PERCENT)
52 | .height(Constants.FULL_PERCENT)
53 | Image($r('app.media.ic_logo'))
54 | .width($r('app.float.192vp'))
55 | .height($r('app.float.192vp'))
56 | .offset({
57 | y: `-${Constants.PERCENTAGE_15}`
58 | })
59 | .objectFit(ImageFit.Contain)
60 |
61 | Column() {
62 | Text($r('app.string.app_name'))
63 | .fontColor(Color.White)
64 | .fontSize($r('app.float.font_size_24fp'))
65 | .fontWeight(FontWeight.Medium)
66 |
67 | // Text($r('app.string.app_name'))
68 | // .fontSize($r('app.float.font_size_16fp'))
69 | // .fontColor(Color.White)
70 | // .margin({
71 | // top: $r('app.float.5')
72 | // })
73 | }
74 | .offset({
75 | y: Constants.PERCENTAGE_25
76 | })
77 | }
78 | }.height(Constants.FULL_SIZE)
79 | .width(Constants.FULL_SIZE)
80 | }
81 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/TreePage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import router from '@ohos.router';
3 | import { TreeItem } from '../bean/TreeBean';
4 | import Constants from '../common/constants/Constants';
5 | import TreeViewModel from '../viewmodel/TreeViewModel';
6 |
7 | /**
8 | * @desc:2-导航
9 | */
10 | @Preview
11 | @Component
12 | export default struct TreePage {
13 | @State treeData: TreeItem[] = [];
14 |
15 | //页面即将显示时
16 | aboutToAppear() {
17 | //1-体系数据
18 | TreeViewModel.getTreeData().then(result => {
19 | console.log('tree>>>', result)
20 | this.treeData = result
21 | })
22 | //2-知识体系下的文章
23 | TreeViewModel.getTreeArticleList(0, 60).then(result => {
24 | console.log('treeArticle>>>', result)
25 | })
26 | }
27 |
28 | //分组-头部组件
29 | @Builder
30 | itemHead(text: string) {
31 | // 列表分组的头部组件,对应联系人分组A、B等位置的组件
32 | Text(text)
33 | .fontSize($r('app.float.20fp'))
34 | .fontWeight(FontWeight.Bold)
35 | .backgroundColor($r('app.color.light_gray'))
36 | .width('100%')
37 | .padding(5)
38 | }
39 |
40 | build() {
41 | List() {
42 | ForEach(this.treeData, (treeItem:TreeItem) => {
43 | ListItemGroup({ header: this.itemHead(treeItem.name) }) {
44 | //循环渲染ListItem
45 | ListItem() {
46 | Flex({ wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceEvenly }) {
47 | ForEach(treeItem.children, (item: TreeItem, index) => {
48 | Navigator({ target: Constants.TreeTabPage_Path, type: NavigationType.Push }) {
49 | Text(item.name)
50 | .textAlign(TextAlign.Center)
51 | .height($r('app.float.30vp'))
52 | .border({ width: 1 })
53 | .borderColor(Color.Black)
54 | .borderRadius(2)
55 | .padding({
56 | top: $r('app.float.2vp'),
57 | bottom: $r('app.float.2vp'),
58 | left: $r('app.float.5vp'),
59 | right: $r('app.float.5vp')
60 | })
61 | .margin($r('app.float.5vp'))
62 | }.params({ index: index, data: treeItem })
63 | })
64 | }.width('90%').padding($r('app.float.10vp'))
65 | }
66 | }
67 | })
68 | }
69 | .height('100%')
70 | .width('100%')
71 | }
72 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/TreeTabPage.ets:
--------------------------------------------------------------------------------
1 | // 导入页面路由模块
2 | import router from '@ohos.router';
3 | import { ProjectItem } from '../bean/ProjectBean';
4 | import Constants from '../common/constants/Constants';
5 | import TitleBar from '../view/TitleBar';
6 | import TreeList from '../view/TreeList';
7 | /**
8 | * @desc:7-导航-条目跳转页面
9 | */
10 |
11 | @Preview
12 | @Entry
13 | @Component
14 | export default struct TreeTabPage {
15 | private tabsController: TabsController = new TabsController()
16 | @State params: object = router.getParams();
17 | @State projectData: ProjectItem[] = [];
18 | @State currentIndex: number = 0;
19 | @State optionsDic: Map = new Map();
20 | //页面即将显示时
21 | aboutToAppear() {
22 | //1-项目分类
23 | this.currentIndex = this.params['index']
24 | this.projectData = (this.params['data'] as ProjectItem).children
25 | this.projectData.forEach((project, index) => {
26 | this.optionsDic[index] = project.id //将tab_index对应的cid放到map中
27 | })
28 | }
29 |
30 | //自定义Tab
31 | @Builder TabBuilder(index: number) {
32 | Column() {
33 | Text(this.projectData[index].name)
34 | .height(Constants.FULL_PERCENT)
35 | .fontSize(this.currentIndex === index ? $r('app.float.24fp') : $r('app.float.18fp'))
36 | .fontWeight(this.currentIndex === index ? Constants.TYPE_FONT_WEIGHT : Constants.DESC_FONT_WEIGHT)
37 | .fontColor($r('app.color.black'))
38 | }
39 | .padding({ left: $r('app.float.8vp'), right: $r('app.float.8vp') })
40 | .margin({
41 | left: index === 0 ? $r('app.float.8vp') : 0,
42 | right: index === this.projectData.length - 1 ? $r('app.float.8vp') : 0
43 | })
44 | }
45 |
46 | build() {
47 | Column() {
48 | TitleBar({ title: (this.params['data'] as ProjectItem).name })
49 | //Tabs
50 | Tabs({ barPosition: BarPosition.Start }) {
51 | ForEach(this.projectData, (projectItem: ProjectItem, index?: number) => {
52 | TabContent() {
53 | TreeList({ index, optionsDic: this.optionsDic, currentIndex: $currentIndex })
54 | }.tabBar(this.TabBuilder(index?index:0))
55 | }, (tabItem: ProjectItem) => JSON.stringify(tabItem))
56 | }
57 | .barHeight($r('app.float.50vp'))
58 | .height(Constants.FULL_PERCENT)
59 | .barMode(BarMode.Scrollable)
60 | .onChange((index: number) => {
61 | this.currentIndex = index;
62 | this.tabsController.changeIndex(this.currentIndex);
63 | })
64 | .vertical(false)
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/WebPage.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import router from '@ohos.router';
17 | import webview from '@ohos.web.webview';
18 | import prompt from '@ohos.promptAction';
19 | import Constants from '../common/constants/Constants';
20 | import TitleBar from '../view/TitleBar';
21 |
22 |
23 | @Preview
24 | @Entry
25 | @Component
26 | struct WebPage {
27 | webController: webview.WebviewController = new webview.WebviewController();
28 | @State params: object = router.getParams();
29 | @State progressVal: number = 0;
30 | @State isLoading: boolean = true;
31 | @State intervalLoading: number = -1;
32 |
33 | aboutToAppear() {
34 | this.intervalLoading = setInterval(() => {
35 | this.progressVal = this.progressVal >= Constants.WebConstant_PROGRESS_MAX ?
36 | Constants.WebConstant_PROGRESS_MIN : (this.progressVal + Constants.WebConstant_PROGRESS_STEP);
37 | }, Constants.WebConstant_MILLI_SECONDS);
38 | }
39 |
40 | build() {
41 | Stack({ alignContent: Alignment.TopStart }) {
42 | Row() {
43 | Column() {
44 | TitleBar({ title: this.params['title'] })
45 |
46 | // Web component loading H5.
47 | Web({ src: this.params['path'], controller: this.webController })
48 | .zoomAccess(false)
49 | .width(Constants.FULL_PERCENT)
50 | .height(Constants.FULL_PERCENT)
51 | .onConfirm((event) => {
52 | return true;
53 | })
54 | .onErrorReceive((event) => {
55 | if (event?.error.getErrorInfo() === 'ERR_INTERNET_DISCONNECTED') {
56 | prompt.showToast({
57 | message: $r('app.string.internet_err'),
58 | duration: Constants.WebConstant_DURATION
59 | })
60 | }
61 | if (event?.error.getErrorInfo() === 'ERR_CONNECTION_TIMED_OUT') {
62 | prompt.showToast({
63 | message: $r('app.string.internet_err'),
64 | duration: Constants.WebConstant_DURATION
65 | })
66 | }
67 | })
68 | .onProgressChange((event) => {
69 | if (event?.newProgress === Constants.WebConstant_PROGRESS_MAX) {
70 | this.isLoading = false;
71 | clearInterval(this.intervalLoading);
72 | this.intervalLoading = -1;
73 | }
74 | })
75 | }
76 | .width(Constants.FULL_PERCENT)
77 | .height(Constants.FULL_PERCENT)
78 | }.width(Constants.FULL_PERCENT)
79 | .height(Constants.FULL_PERCENT)
80 |
81 | if (this.isLoading) {
82 | Progress({
83 | value: Constants.WebConstant_PROGRESS_MIN,
84 | total: Constants.WebConstant_PROGRESS_MAX,
85 | type: ProgressType.ScaleRing
86 | })
87 | .color(Color.Grey)
88 | .value(this.progressVal)
89 | .width(Constants.WebConstant_PROGRESS_WIDTH)
90 | .height(Constants.WebConstant_PROGRESS_WIDTH)
91 | .style({
92 | strokeWidth: Constants.WebConstant_PROGRESS_STROKE_WIDTH,
93 | scaleCount: Constants.WebConstant_PROGRESS_SCALE_COUNT,
94 | scaleWidth: Constants.WebConstant_PROGRESS_SCALE_WIDTH
95 | })
96 | .zIndex(1)
97 | .position({
98 | x: Constants.WebConstant_PROGRESS_POSITION_X,
99 | y: Constants.WebConstant_PROGRESS_POSITION_Y
100 | })
101 | }
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/Logger.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import hilog from '@ohos.hilog';
17 |
18 | const LOGGER_PREFIX: string = 'News Release';
19 |
20 | class Logger {
21 | private domain: number;
22 | private prefix: string;
23 |
24 | // format Indicates the log format string.
25 | private format: string = '%{public}s, %{public}s';
26 |
27 | /**
28 | * constructor.
29 | *
30 | * @param prefix Identifies the log tag.
31 | * @param domain Indicates the service domain, which is a hexadecimal integer ranging from 0x0 to 0xFFFFF
32 | * @param args Indicates the log parameters.
33 | */
34 | constructor(prefix: string = '', domain: number = 0xFF00) {
35 | this.prefix = prefix;
36 | this.domain = domain;
37 | }
38 |
39 | debug(...args: string[]): void {
40 | hilog.debug(this.domain, this.prefix, this.format, args);
41 | }
42 |
43 | info(...args: string[]): void {
44 | hilog.info(this.domain, this.prefix, this.format, args);
45 | }
46 |
47 | warn(...args: string[]): void {
48 | hilog.warn(this.domain, this.prefix, this.format, args);
49 | }
50 |
51 | error(...args: string[]): void {
52 | hilog.error(this.domain, this.prefix, this.format, args);
53 | }
54 | }
55 |
56 | export default new Logger(LOGGER_PREFIX);
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/PreferencesUtils.ets:
--------------------------------------------------------------------------------
1 | import preferences from '@ohos.data.preferences';
2 | import dataPreferences from '@ohos.data.preferences';
3 | import Logger from './Logger';
4 |
5 | const PREFERENCES_NAME = 'theme.db'
6 | let preferenceTheme: preferences.Preferences| null = null;
7 | const TAG: string = '[Index]'
8 |
9 | class PreferencesUtils {
10 | constructor() {
11 | this.createDataPreferences()
12 | }
13 |
14 | async createDataPreferences() {
15 | preferenceTheme = await dataPreferences.getPreferences(globalThis.abilityContext, PREFERENCES_NAME);
16 | }
17 |
18 |
19 | /**
20 | * 保存String数据
21 | * @param str
22 | */
23 | async putStringData(key: string, value: string) {
24 | Logger.info(TAG, `Put begin`)
25 | if (preferenceTheme !== null) {
26 | await preferenceTheme.put(key, value)
27 | await preferenceTheme.flush()
28 | }
29 | }
30 |
31 | /**
32 | * @returns
33 | */
34 | async getStringData(key: string) {
35 | Logger.info(TAG, `Get begin`)
36 | if (preferenceTheme !== null) {
37 | let data: string = ''
38 | data = await preferenceTheme.get(key, '') as string
39 | return data;
40 | }else{
41 | return ''
42 | }
43 | }
44 |
45 | async putNumberData(key: string, num: number) {
46 | Logger.info(TAG, `Put begin`)
47 | if (preferenceTheme !== null) {
48 | await preferenceTheme.put(key, num)
49 | await preferenceTheme.flush()
50 | }
51 | }
52 |
53 | /**
54 | * getNumber数据
55 | * @returns
56 | */
57 | async getNumberData(key: string) {
58 | Logger.info(TAG, `Get begin`)
59 | if (preferenceTheme !== null) {
60 | let data: number = 0;
61 | data = await preferenceTheme.get(key, -1) as number
62 | return data;
63 | }else {
64 | return -1
65 | }
66 | }
67 | }
68 |
69 | let preferencesUtil = new PreferencesUtils();
70 |
71 | export default preferencesUtil as PreferencesUtils;
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/Utils.ets:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @desc:工具类
4 | */
5 |
6 | //1-判断是否为空字符串
7 | const isEmpty = (data:string|[]|number|object) => {
8 | return data == undefined || data == "" || (data as []).length <= 0 || data === '0'
9 |
10 | };
11 | //2-格式化字符串
12 | const formatHtml = (html:string) => {
13 | let data = ''
14 | if (!isEmpty(html)) {
15 | let regSymbol = RegExp("&.*;")
16 | let regHtml = RegExp(/<[^>]*>/g);
17 | data = html.replace(regSymbol, '').replace(regHtml, '')
18 | }
19 | return data
20 | }
21 |
22 | export {
23 | isEmpty,
24 | formatHtml
25 | };
--------------------------------------------------------------------------------
/entry/src/main/ets/view/ArticleItem.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:文章Item
3 | */
4 | import * as Utils from "../utils/Utils";
5 | import { Article } from '../bean/ArticleBean'
6 | import Constants from '../common/constants/Constants';
7 | import { when } from '@ohos/hypium';
8 |
9 | @Component
10 | export default struct ArticleItem {
11 | article: Article = new Article()
12 | @State isTop: boolean = false;
13 | @State hasTag: boolean = false;
14 | @State tag: string = '';
15 | @State author: string | number = '';
16 | @State title: string = '';
17 | @State desc: string = '';
18 | @State hasPic: boolean = false;
19 | @State hasSuperChapterName: boolean = false;
20 | @State superChapterName: string = '';
21 | @State hasChapterName: boolean = false;
22 | @State chapterName: string = '';
23 |
24 | aboutToAppear() {
25 | let item = this.article
26 |
27 | this.isTop = item.isTop;
28 | this.hasTag = !Utils.isEmpty(item.tags as []);
29 | this.tag = !this.hasTag ? '暂无' : item.tags[0].name;
30 | this.author = Utils.isEmpty(item.author) ? Utils.isEmpty(item.shareUser) ? '' : item.shareUser : item.author;
31 |
32 |
33 | //this.author = Utils.isEmpty(item.author) ? Utils.isEmpty(item.shareUser) ? '' : item.shareUser : item.author;
34 | this.title = Utils.formatHtml(item.title);
35 | this.desc = Utils.formatHtml(item.desc)
36 | this.hasPic = !Utils.isEmpty(item.envelopePic)
37 | this.hasSuperChapterName = !Utils.isEmpty(item.superChapterName)
38 | this.superChapterName = Utils.isEmpty(item.superChapterName) ? '' : Utils.formatHtml(item.superChapterName)
39 | this.hasChapterName = !Utils.isEmpty(item.chapterName)
40 | this.chapterName = Utils.isEmpty(item.chapterName) ? '' : Utils.formatHtml(item.chapterName)
41 |
42 | }
43 |
44 | build() {
45 | Column() {
46 | //第一行
47 | Row() {
48 |
49 | //1-tag
50 | if (this.hasTag) {
51 | Text(this.tag)
52 | .height($r('app.float.23vp'))
53 | .fontSize($r('app.float.12fp'))
54 | .textAlign(TextAlign.Center)
55 | .borderRadius($r('app.float.3vp'))
56 | .fontColor($r('app.color.white'))
57 | .backgroundColor('red')
58 | .padding({
59 | left: $r('app.float.10vp'),
60 | right: $r('app.float.10vp'),
61 | top: $r('app.float.5vp'),
62 | bottom: $r('app.float.5vp')
63 | })
64 | }
65 | Row() {
66 | Image($r('app.media.ic_me_normal')).width($r('app.float.18vp')).height($r('app.float.18vp'))
67 | Text(this.author.toString()).margin({ left: $r('app.float.5vp') }) //2-author
68 | }.margin({ left: $r('app.float.5vp'), right: $r('app.float.5vp') })
69 |
70 | Row() {
71 | Image($r('app.media.ic_clock')).width($r('app.float.18vp')).height($r('app.float.18vp'))
72 | Text(this.article.niceDate) //3-time
73 | }
74 | }.width(Constants.FULL_PERCENT).justifyContent(FlexAlign.SpaceBetween)
75 | //第2行
76 | Flex({ direction: FlexDirection.Row }) {
77 | Column() {
78 | Text(this.title)
79 | //.width(Constants.FULL_PERCENT)
80 | .maxLines(2)
81 | .textOverflow({ overflow: TextOverflow.Ellipsis })
82 | .fontSize($r('app.float.18fp'))
83 | .fontColor(Color.Black)
84 | .align(Alignment.TopStart)
85 | Text(this.desc)
86 | //.width(Constants.FULL_PERCENT)
87 | .maxLines(2)
88 | .textOverflow({ overflow: TextOverflow.Ellipsis })
89 | .fontColor(Color.Gray)
90 | .align(Alignment.TopStart)
91 | }.flexGrow(1)
92 | //.width('70%')
93 | .alignItems(HorizontalAlign.Start)
94 |
95 | if (this.hasPic) {
96 | //Image('https://img1.baidu.com/it/u=2653588009,1450076812&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1699722000&t=b4f916a93f7e4735cf7c4c69416ab2fb')
97 | Image(this.article.envelopePic)
98 | .width($r('app.float.60vp'))
99 | .height('100%')
100 | }
101 | }.height($r('app.float.80vp')).margin({ top: $r('app.float.5vp') })
102 | //第3行
103 | Row() {
104 | //置顶
105 | if (this.isTop) {
106 | Text('置顶')
107 | .height($r('app.float.23vp'))
108 | .fontSize($r('app.float.12fp'))
109 | .borderRadius($r('app.float.3vp'))
110 | .textAlign(TextAlign.Center)
111 | .fontColor($r('app.color.white'))
112 | .backgroundColor($r('app.color.dark_orange'))
113 | .padding({
114 | left: $r('app.float.10vp'),
115 | right: $r('app.float.10vp'),
116 | top: $r('app.float.5vp'),
117 | bottom: $r('app.float.5vp')
118 | })
119 | .margin({ right: $r('app.float.10vp') })
120 | }
121 |
122 | if (this.hasSuperChapterName) {
123 | Text(this.superChapterName)
124 | .height($r('app.float.23vp'))
125 | .fontSize($r('app.float.12fp'))
126 | .borderRadius($r('app.float.3vp'))
127 | .textAlign(TextAlign.Center)
128 | .fontColor($r('app.color.white'))
129 | .backgroundColor($r('app.color.olive'))
130 | .padding({
131 | left: $r('app.float.10vp'),
132 | right: $r('app.float.10vp'),
133 | top: $r('app.float.5vp'),
134 | bottom: $r('app.float.5vp')
135 | })
136 | .margin({ right: $r('app.float.10vp') })
137 | }
138 | if (this.hasChapterName) {
139 | Text(this.chapterName)
140 | .height($r('app.float.23vp'))
141 | .fontSize($r('app.float.12fp'))
142 | .borderRadius($r('app.float.3vp'))
143 | .textAlign(TextAlign.Center)
144 | .fontColor($r('app.color.white'))
145 | .backgroundColor($r('app.color.teal'))
146 | .padding({
147 | left: $r('app.float.10vp'),
148 | right: $r('app.float.10vp'),
149 | top: $r('app.float.5vp'),
150 | bottom: $r('app.float.5vp')
151 | })
152 | .margin({ right: $r('app.float.10vp') })
153 | }
154 | }.width(Constants.FULL_PERCENT).justifyContent(FlexAlign.Start).margin({ top: $r('app.float.5vp') })
155 |
156 | }
157 | //.height(160)
158 | .width(Constants.FULL_PERCENT)
159 | .padding({
160 | top: $r('app.float.5vp'),
161 | bottom: $r('app.float.5vp'),
162 | left: $r('app.float.10vp'),
163 | right: $r('app.float.10vp')
164 | })
165 | .borderWidth(0.5)
166 | .borderColor(Color.Gray)
167 | .backgroundColor('#FFF1F3F5')
168 | }
169 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/InfoItem.ets:
--------------------------------------------------------------------------------
1 | import * as Utils from "../utils/Utils";
2 | /**
3 | * 积分排行或个人积分——Item,三行或四行数据
4 | */
5 | @Preview
6 | @Component
7 | export default struct InfoItem {
8 | param1: string = '';
9 | param2: string = '';
10 | param3: string = '';
11 | param4: string = '';
12 |
13 | build() {
14 | Column({ space: 5 }) {
15 | Text(this.param1)
16 | Text(this.param2)
17 | Text(this.param3)
18 | if (!Utils.isEmpty(this.param4)){
19 | Text(this.param4)
20 | }
21 | }.width('100%')
22 | .borderRadius(5)
23 | .padding({ left: 5, right: 5, top: 10, bottom: 10 })
24 | .backgroundColor($r('app.color.white_smoke'))
25 | }
26 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/MineFunc.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:我的-常用功能
3 | */
4 | import Constants from '../common/constants/Constants';
5 |
6 | interface FuncInterface {
7 | 'name': string;
8 | 'backgroundColor': Color;
9 | }
10 |
11 | @Preview
12 | @Component
13 | export default struct MineFunc {
14 | @State bgColors: Color[] = [Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Pink, Color.Grey, Color.Blue, Color.Brown];
15 | gridData:FuncInterface[]= [
16 | {
17 | name: "工具",
18 | backgroundColor: Color.Red
19 | },
20 | {
21 | name: "问答",
22 | backgroundColor: Color.Orange
23 | },
24 | {
25 | name: "消息",
26 | backgroundColor: Color.Yellow
27 | },
28 | {
29 | name: "课程",
30 | backgroundColor: Color.Green
31 | },
32 | {
33 | name: "待办清单",
34 | backgroundColor: Color.Pink
35 | },
36 | {
37 | name: "分享文章",
38 | backgroundColor: Color.Grey
39 | },
40 | ]
41 | @State currentBp: string = 'unknown';
42 |
43 | build() {
44 | Column() {
45 | Text('常用功能')
46 | .fontSize($r('app.float.20fp'))
47 | .fontWeight(FontWeight.Bold)
48 | .margin({ bottom: $r('app.float.10vp') })
49 |
50 | GridRow({ columns: 3 }) {
51 | ForEach(this.gridData, (item:FuncInterface, index) => {
52 | GridCol() {
53 | Row() {
54 | Text(`${item.name}`).textAlign(TextAlign.Center).width('100%')
55 | }.width('100%').height(120)
56 | }.backgroundColor(item.backgroundColor)
57 | })
58 | }
59 | .width('100%').height('100%')
60 | .onBreakpointChange((breakpoint) => {
61 | this.currentBp = breakpoint
62 | })
63 | }
64 | .height(600)
65 | .alignItems(HorizontalAlign.Start)
66 | .padding({ left: $r('app.float.10vp'), right: $r('app.float.10vp') })
67 | .width(Constants.FULL_PERCENT)
68 | }
69 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/MineHead.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:我的-头部信息
3 | */
4 | import router from '@ohos.router';
5 | import { UserData, UserInfo } from '../bean/UserInfoBean';
6 | import Constants from '../common/constants/Constants'
7 | import * as Utils from "../utils/Utils";
8 | import MeViewModel from '../viewmodel/MeViewModel';
9 | import prompt from '@ohos.promptAction';
10 |
11 | @Preview
12 | @Component
13 | export default struct MineHead {
14 | @State userData: UserData = new UserData()
15 | @State isLogin: boolean = false
16 | @State rank: string = '';
17 | @State collectIds: string = '';
18 | @State level: string = '';
19 | @State coinCount: string = '';
20 |
21 | aboutToAppear() {
22 | MeViewModel.getUserInfo().then((data: UserData) => {
23 | this.userData = data;
24 | }).catch((err:Error) => {
25 | this.userData = new UserData();
26 | })
27 | }
28 |
29 | // 在Home页面中
30 | jumpLoginClick(): void {
31 | router.pushUrl({
32 | url: Constants.LoginRegister_Path // 目标url
33 | }, router.RouterMode.Standard, (err) => {
34 | if (err) {
35 | console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
36 | return;
37 | }
38 | console.info('Invoke pushUrl succeeded.');
39 | });
40 | }
41 |
42 | jumpPath(path: string) {
43 | if (Utils.isEmpty(this.userData.userInfo.username)) {
44 | prompt.showToast({ message: '请先登录账号' })
45 | return
46 | }
47 | console.log("path=>", path);
48 | switch (path){
49 | case Constants.COIN:
50 | case Constants.RANK:
51 | router.pushUrl({ url: Constants.InfoPage_Path, params: { title: path } })
52 | break;
53 | }
54 | }
55 |
56 | @Builder
57 | InfoItem(title: string, content?: string, click?: () => void) {
58 | Column() {
59 | Text(title)
60 | .fontSize($r('app.float.18fp'))
61 | .fontWeight(FontWeight.Bold)
62 | Text(Utils.isEmpty(content) ? '——' : content)
63 | .margin({ top: $r('app.float.3vp') })
64 | }.flexGrow(1)
65 | .alignItems(HorizontalAlign.Center)
66 | .onClick(click)
67 | }
68 |
69 | build() {
70 | Column() {
71 | //1-设置
72 | Flex({ alignItems: ItemAlign.Center }) {
73 | Text('')
74 | .size({ width: $r('app.float.60vp'), height: $r('app.float.60vp') })
75 |
76 | Text('我的')
77 | .textAlign(TextAlign.Center)
78 | .fontColor(Color.White)
79 | .maxLines(1)
80 | .fontSize($r('app.float.22fp'))
81 | .flexGrow(1)
82 |
83 | Image($r('app.media.ic_setting'))
84 | .size({ width: $r('app.float.30vp'), height: $r('app.float.30vp') })
85 | .margin({ right: $r('app.float.10vp') })
86 | .onClick(() => {
87 | router.pushUrl({ url: Constants.SettingPage_Path })
88 | })
89 | }.width(Constants.FULL_PERCENT)
90 | .backgroundColor($r('app.color.dodger_blue'))
91 |
92 | //2-底部
93 | Column() {
94 |
95 | //1-头像行-信息
96 | Flex({ alignItems: ItemAlign.Center }) {
97 | Image($r('app.media.ic_user'))
98 | .margin({ left: $r('app.float.20vp') })
99 | .size({ width: $r('app.float.60vp'), height: $r('app.float.60vp') })
100 |
101 | Text(!Utils.isEmpty(this.userData.userInfo.username) ? `${this.userData.userInfo.username}` : '欢迎登陆')
102 | .textAlign(TextAlign.Start)
103 | .maxLines(1)
104 | .fontSize($r('app.float.18fp'))
105 | .margin({ left: $r('app.float.10vp'), right: $r('app.float.10vp') })
106 | .flexGrow(1)
107 |
108 | Image($r('app.media.ic_arrow_right'))
109 | .size({ width: $r('app.float.30vp'), height: $r('app.float.30vp') })
110 |
111 | }.width(Constants.FULL_PERCENT)
112 | .onClick(() => {
113 | if (Utils.isEmpty(this.userData.userInfo.username)) {
114 | this.jumpLoginClick()
115 | }
116 | })
117 |
118 | //2-文章信息
119 | // Flex({ justifyContent: FlexAlign.SpaceBetween }) {
120 | // this.InfoItem('排名',!Utils.isEmpty(this.userData) ? `${this.userData.coinInfo.rank}}` : '——')
121 | // this.InfoItem('收藏',!Utils.isEmpty(this.userData) ? `${this.userData.userInfo.collectIds.length.toString()}` : '——')
122 | // this.InfoItem('等级',!Utils.isEmpty(this.userData) ? `${this.userData.coinInfo.level.toString()}` : '——')
123 | // this.InfoItem('积分',!Utils.isEmpty(this.userData) ? `${this.userData.coinInfo.coinCount.toString()}` : '——')
124 | // }.margin({ top: $r('app.float.40vp') })
125 |
126 | if (!Utils.isEmpty(this.userData.userInfo.username)) {
127 | Flex({ justifyContent: FlexAlign.SpaceBetween }) {
128 | this.InfoItem('排名', this.userData.coinInfo.rank, ():void => this.jumpPath(Constants.RANK))
129 | this.InfoItem('收藏', `${this.userData.userInfo.collectIds.length}`, ():void => this.jumpPath(Constants.COLLECT))
130 | this.InfoItem('等级', `${this.userData.coinInfo.level}`, ():void => this.jumpPath(Constants.LEVEL))
131 | this.InfoItem('积分', `${this.userData.coinInfo.coinCount}`, ():void => this.jumpPath(Constants.COIN))
132 | }.margin({ top: $r('app.float.40vp') })
133 | } else {
134 | Flex({ justifyContent: FlexAlign.SpaceBetween }) {
135 | this.InfoItem('排名', '——', ():void => this.jumpPath(Constants.RANK))
136 | this.InfoItem('收藏', '——', ():void => this.jumpPath(Constants.COLLECT))
137 | this.InfoItem('等级', '——', ():void => this.jumpPath(Constants.LEVEL))
138 | this.InfoItem('积分', '——', ():void => this.jumpPath(Constants.COIN))
139 | }.margin({ top: $r('app.float.40vp') })
140 | }
141 | }
142 | .width(Constants.FULL_PERCENT)
143 | .padding({
144 | left: $r('app.float.10vp'),
145 | right: $r('app.float.10vp'),
146 | top: $r('app.float.30vp'),
147 | bottom: $r('app.float.20vp')
148 | })
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/MsgItemView.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:消息-未/已读消息Item
3 | */
4 | import Constants from '../common/constants/Constants'
5 |
6 | import { MsgData, MsgItem } from '../bean/MsgBean'
7 |
8 |
9 | @Preview
10 | @Component
11 | export default struct MsgItemView {
12 | msgItem: MsgItem = new MsgItem()
13 | @State msg: string = ''
14 | @State content: string = 'kotlin 协程,CoroutineScope 调用 cancel() 后,无法再次执行 launch,如何理解这块。如下代码val scope = CoroutineScope(Dispatchers.Main)scope.launch Log.d(TAG, "cancelJob: before cancel")...'
15 |
16 | build() {
17 | Column() {
18 | //第一行
19 | Flex({ justifyContent: FlexAlign.SpaceBetween }) {
20 | Row() {
21 | Image($r('app.media.ic_me_normal')).width($r('app.float.18vp')).height($r('app.float.18vp'))
22 | Text(this.msgItem.fromUser).margin({ left: $r('app.float.5vp') }) //2-author
23 | }.margin({ left: $r('app.float.5vp'), right: $r('app.float.5vp') })
24 |
25 | Text(this.msgItem.tag)
26 | .height($r('app.float.23vp'))
27 | .fontSize($r('app.float.12fp'))
28 | .textAlign(TextAlign.Center)
29 | .maxLines(1)
30 | .borderRadius($r('app.float.3vp'))
31 | .fontColor($r('app.color.white'))
32 | .backgroundColor($r('app.color.fire_brick'))
33 | .padding({
34 | left: $r('app.float.10vp'),
35 | right: $r('app.float.10vp'),
36 | })
37 |
38 | Row() {
39 | Image($r('app.media.ic_clock')).width($r('app.float.18vp')).height($r('app.float.18vp'))
40 | Text(this.msgItem.niceDate).margin({ left: $r('app.float.5vp') }) //2-author
41 | }.margin({ left: $r('app.float.5vp'), right: $r('app.float.5vp') })
42 | }
43 | //第2行呢容
44 | Text(this.msgItem.title)
45 | .height($r('app.float.30vp'))
46 | .fontSize($r('app.float.12fp'))
47 | .textAlign(TextAlign.Start)
48 | .borderRadius($r('app.float.3vp'))
49 | .fontColor($r('app.color.white'))
50 | .maxLines(1)
51 | .textOverflow({ overflow: TextOverflow.Ellipsis })
52 | .width(Constants.FULL_PERCENT)
53 | .borderRadius(6)
54 | .backgroundColor($r('app.color.royal_blue'))
55 | .margin({ top: $r('app.float.10vp') })
56 | .padding({
57 | left: $r('app.float.10vp'),
58 | right: $r('app.float.10vp'),
59 | top: $r('app.float.5vp'),
60 | bottom: $r('app.float.5vp')
61 | })
62 | //第3行呢容
63 | Text(this.msgItem.message)
64 | .textAlign(TextAlign.Start)
65 | .width(Constants.FULL_PERCENT)
66 | .maxLines(3)
67 | .margin({ top: $r('app.float.10vp') })
68 | }
69 | .padding(10)
70 | .backgroundColor($r('app.color.white_smoke'))
71 | .borderWidth(5)
72 | .borderColor($r('app.color.light_gray'))
73 | }
74 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/MsgReadList.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:消息-已读消息
3 | */
4 | import { MsgData, MsgItem } from '../bean/MsgBean'
5 | import MsgViewModel from '../viewmodel/MsgViewModel'
6 | import MsgItemView from './MsgItemView'
7 | import * as Utils from "../utils/Utils";
8 | import { NavigatorModel } from '../viewmodel/NavigatorModel';
9 | import Constants from '../common/constants/Constants';
10 | import router from '@ohos.router';
11 |
12 |
13 | @Component
14 | export default struct MsgReadList {
15 | @State msgList: MsgItem[] = []
16 |
17 | aboutToAppear() {
18 | MsgViewModel.getMsgRead(1).then((msgData: MsgData) => {
19 | this.msgList = msgData.datas
20 | console.log('readMsg>>>', msgData)
21 | })
22 | }
23 |
24 | @Builder
25 | MsgDataView() {
26 | Scroll() {
27 | Column() {
28 | ForEach(this.msgList, (item: MsgItem, index) => {
29 | Navigator({ target: Constants.WebPage_Path, type: NavigationType.Push }) {
30 | MsgItemView({ msgItem: item })
31 | }.params({ path: item.link, title: item.title } as NavigatorModel)
32 | })
33 | }
34 | }
35 | }
36 |
37 | @Builder
38 | MsgNoLoginView() {
39 | Text('登录后查看消息')
40 | .textAlign(TextAlign.Center)
41 | //.width('100%')
42 | //.height('100%')
43 | .backgroundColor($r('app.color.deep_sky_blue'))
44 | .padding({top:$r('app.float.10vp'),bottom:$r('app.float.10vp'),left:$r('app.float.20vp'),right:$r('app.float.20vp')})
45 | .borderRadius($r('app.float.5vp'))
46 | .onClick(() => {
47 | router.pushUrl({
48 | url: Constants.LoginRegister_Path // 目标url
49 | })
50 | })
51 | }
52 |
53 | @Builder
54 | MsgNoView() {
55 | Text('暂时没有数据哦')
56 | .textAlign(TextAlign.Center)
57 | .width('100%')
58 | .height('100%')
59 | }
60 |
61 | build() {
62 | if (!Utils.isEmpty(AppStorage.Get(Constants.Cookie) as string)) {
63 | if (Utils.isEmpty(this.msgList)) {
64 | this.MsgNoView()
65 | } else {
66 | this.MsgDataView()
67 | }
68 | } else {
69 | this.MsgNoLoginView()
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/MsgUnreadList.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:消息-未读消息
3 | */
4 |
5 | import MsgViewModel from '../viewmodel/MsgViewModel'
6 | import MsgItemView from './MsgItemView'
7 | import { MsgData, MsgItem } from '../bean/MsgBean'
8 | import * as Utils from "../utils/Utils";
9 | import Constants from '../common/constants/Constants';
10 | import router from '@ohos.router';
11 |
12 | @Component
13 | export default struct MsgUnreadList {
14 | @State msgList: MsgItem[] = []
15 |
16 | aboutToAppear() {
17 | // MsgViewModel.getMsgUnRead().then(result => {
18 | // console.log('unreadMsg>>>', result)
19 | // })
20 |
21 | MsgViewModel.getMsgUnRead().then((msgData: MsgData) => {
22 | this.msgList = msgData.datas
23 | console.log('readMsg>>>', msgData)
24 | })
25 | }
26 |
27 | @Builder
28 | MsgDataView() {
29 | Scroll() {
30 | Column() {
31 | ForEach(this.msgList, (item:MsgItem, index) => {
32 | MsgItemView({ msgItem: item })
33 | })
34 | }
35 | }
36 | }
37 |
38 | @Builder
39 | MsgNoLoginView() {
40 | Text('登录后查看消息')
41 | .textAlign(TextAlign.Center)
42 | //.width('100%')
43 | //.height('100%')
44 | .backgroundColor($r('app.color.deep_sky_blue'))
45 | .padding({top:$r('app.float.10vp'),bottom:$r('app.float.10vp'),left:$r('app.float.20vp'),right:$r('app.float.20vp')})
46 | .borderRadius($r('app.float.5vp'))
47 | .onClick(() => {
48 | router.pushUrl({
49 | url: Constants.LoginRegister_Path // 目标url
50 | })
51 | })
52 | }
53 |
54 | @Builder
55 | MsgNoView() {
56 | Text('暂时没有数据哦')
57 | .textAlign(TextAlign.Center)
58 | .width('100%')
59 | .height('100%')
60 | }
61 |
62 | build() {
63 | if (!Utils.isEmpty(AppStorage.Get(Constants.Cookie) as string)) {
64 | if (Utils.isEmpty(this.msgList)) {
65 | this.MsgNoView()
66 | } else {
67 | this.MsgDataView()
68 | }
69 | } else {
70 | this.MsgNoLoginView()
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/ProjectList.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:项目-列表
3 | */
4 | import { Article, ArticleList } from '../bean/ArticleBean';
5 | import Constants from '../common/constants/Constants';
6 | import { NavigatorModel } from '../viewmodel/NavigatorModel';
7 | import ProjectViewModel from '../viewmodel/ProjectViewModel';
8 | import ArticleItem from './ArticleItem';
9 | import * as Utils from "../utils/Utils";
10 | import { PullToRefresh } from '@ohos/pulltorefresh'
11 | import prompt from '@ohos.promptAction';
12 |
13 | @Component
14 | export default struct ProjectList {
15 | index: number = 0;
16 | optionsDic: Map = new Map
17 | @Watch('changeTab') @Link currentIndex: number;
18 | @State articleListData: ArticleList = new ArticleList();
19 | @State articleData: Article[] = [];
20 | @State pageNum: number = 1; //分页page
21 | private scroller: Scroller = new Scroller(); // 需绑定列表或宫格组件
22 |
23 | aboutToAppear() {
24 | // Load data.
25 | this.changeTab()
26 | }
27 |
28 | //与@Watch('changeTab')中的changeTab保持一致。 @Watch装饰器:状态变量更改通知 @Link装饰器:父子双向同步
29 | changeTab() {
30 | if (this.currentIndex !== this.index) {
31 | return;
32 | }
33 | this.getProjectListData(this.pageNum);
34 | }
35 |
36 | getProjectListData(page: number) {
37 | //2-项目列表,page从1开始
38 | ProjectViewModel.getProjectList(page, this.optionsDic[this.currentIndex]).then((data: ArticleList) => {
39 | console.log('getProjectList>>>', data)
40 | this.articleListData = data
41 | this.articleData.push(...data.datas)
42 | })
43 | // ProjectViewModel.getProjectList(1, 294).then((data: ArticleList) => {
44 | // this.articleListData = data
45 | // })
46 | }
47 |
48 | @Builder
49 | NoView() {
50 | Text('暂时没有数据哦')
51 | .textAlign(TextAlign.Center)
52 | .width('100%')
53 | .height('100%')
54 | }
55 |
56 | @Builder
57 | ListView() {
58 | List({ scroller: this.scroller }) {
59 | ForEach(this.articleData, (article: Article) => {
60 | ListItem() {
61 | Navigator({ target: Constants.WebPage_Path, type: NavigationType.Push }) {
62 | ArticleItem({ article: article })
63 | }.params({ path: article.link, title: article.title } as NavigatorModel)
64 | }
65 | })
66 | }.width(Constants.FULL_PERCENT)
67 | .height(Constants.FULL_PERCENT)
68 | .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果
69 | }
70 |
71 | build() {
72 | if (Utils.isEmpty(this.articleListData.datas)) {
73 | this.NoView()
74 | } else {
75 | Column() {
76 | PullToRefresh({
77 | data: this.articleData,
78 | scroller: this.scroller,
79 | customList: () => this.ListView(),
80 | onRefresh: () => {
81 | return new Promise((resolve, reject) => {
82 | setTimeout(() => {
83 | resolve('刷新成功');
84 | //this.articleData = null
85 | this.pageNum = 1;
86 | this.getProjectListData(this.pageNum)
87 | }, 1000);
88 | });
89 | },
90 | onLoadMore: () => {
91 | return new Promise((resolve, reject) => {
92 | setTimeout(() => {
93 | resolve('onLoadMore');
94 | if (!this.articleListData.over) {
95 | this.getProjectListData(++this.pageNum)
96 | } else {
97 | prompt.showToast({ message: $r('app.string.no_more_data') })
98 | }
99 | }, 1000);
100 | });
101 | },
102 | customLoad: null,
103 | customRefresh: null,
104 | })
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/entry/src/main/ets/view/TitleBar.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import Constants from '../common/constants/Constants'
3 | /**
4 | * TitleBar-标题栏
5 | */
6 | @Component
7 | export default struct TitleBar {
8 | title: string = '' //中间标题
9 |
10 | build() {
11 |
12 | //1-头部
13 | Flex({ alignItems: ItemAlign.Center }) {
14 | Image($r('app.media.ic_arrow_left'))
15 | .size({ width: $r('app.float.30vp'), height: $r('app.float.30vp') })
16 | .margin({ right: $r('app.float.10vp') })
17 | .onClick(() => {
18 | router.back()
19 | })
20 | Text(this.title)
21 | .textAlign(TextAlign.Center)
22 | .fontColor(Color.White)
23 | .maxLines(1)
24 | .fontSize($r('app.float.22fp'))
25 | .flexGrow(1)
26 |
27 | Text('')
28 | .width($r('app.float.30vp'))
29 | .height($r('app.float.30vp'))
30 | }.width(Constants.FULL_PERCENT)
31 | .height($r('app.float.60vp'))
32 | .backgroundColor($r('app.color.dodger_blue'))
33 | }
34 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/view/TreeList.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:体系-知识导航-列表
3 | */
4 | import { Article, ArticleList } from '../bean/ArticleBean';
5 | import Constants from '../common/constants/Constants';
6 | import { NavigatorModel } from '../viewmodel/NavigatorModel';
7 | import TreeViewModel from '../viewmodel/TreeViewModel';
8 | import ArticleItem from './ArticleItem';
9 | import * as Utils from "../utils/Utils";
10 | import { PullToRefresh } from '@ohos/pulltorefresh'
11 | import prompt from '@ohos.promptAction';
12 |
13 | @Component
14 | export default struct TreeList {
15 | index: number = 0;
16 | optionsDic: Map = new Map
17 | @Watch('changeTab') @Link currentIndex: number;
18 | @State articleListData: ArticleList = new ArticleList();
19 | @State articleData: Article[] = [];
20 | @State pageNum: number = 0; //分页page
21 | private scroller: Scroller = new Scroller(); // 需绑定列表或宫格组件
22 |
23 | aboutToAppear() {
24 | // Load data.
25 | this.changeTab()
26 | }
27 |
28 | //与@Watch('changeTab')中的changeTab保持一致。 @Watch装饰器:状态变量更改通知 @Link装饰器:父子双向同步
29 | changeTab() {
30 | //2-项目列表,page从0开始
31 | this.getTreeListData(this.pageNum);
32 |
33 | }
34 |
35 | getTreeListData(page: number) {
36 | //2-项目列表,page从1开始
37 | TreeViewModel.getTreeArticleList(page, this.optionsDic[this.currentIndex]).then((data: ArticleList) => {
38 | console.log('getProjectList>>>', data)
39 | this.articleListData = data
40 | this.articleData.push(...data.datas)
41 | })
42 | }
43 |
44 | @Builder
45 | NoView() {
46 | Text('暂时没有数据哦')
47 | .textAlign(TextAlign.Center)
48 | .width('100%')
49 | .height('100%')
50 | }
51 |
52 | @Builder
53 | ListView() {
54 | List({ scroller: this.scroller }) {
55 | ForEach(this.articleData, (article: Article) => {
56 | ListItem() {
57 | Navigator({ target: Constants.WebPage_Path, type: NavigationType.Push }) {
58 | ArticleItem({ article: article })
59 | }.params({ path: article.link, title: article.title } as NavigatorModel)
60 | }
61 | })
62 | }
63 | .width(Constants.FULL_PERCENT)
64 | .height(Constants.FULL_PERCENT)
65 | .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果
66 | }
67 |
68 | build() {
69 | if (Utils.isEmpty(this.articleData)) {
70 | this.NoView()
71 | } else {
72 | Column() {
73 | PullToRefresh({
74 | data: this.articleData,
75 | scroller: this.scroller,
76 | customList: () => this.ListView(),
77 | onRefresh: () => {
78 | return new Promise((resolve, reject) => {
79 | setTimeout(() => {
80 | resolve('刷新成功');
81 | //this.articleData = null
82 | this.pageNum = 0;
83 | this.getTreeListData(this.pageNum)
84 | }, 1000);
85 | });
86 | },
87 | onLoadMore: () => {
88 | return new Promise((resolve, reject) => {
89 | setTimeout(() => {
90 | resolve('onLoadMore');
91 | if (!this.articleListData.over) {
92 | this.getTreeListData(++this.pageNum)
93 | } else {
94 | prompt.showToast({ message: $r('app.string.no_more_data') })
95 | }
96 | }, 1000);
97 | });
98 | },
99 | customLoad: null,
100 | customRefresh: null,
101 | })
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/BottomTabsModel.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | import { BottomTabsItem } from '../common/bean/BottomTabsItem';
17 |
18 | export const BottomTabsList: Array = [
19 | {
20 | icon: $r('app.media.ic_home_normal'),
21 | iconSelected: $r('app.media.ic_home_selected'),
22 | text: $r('app.string.bottom_text_home')
23 | },
24 | {
25 | icon: $r('app.media.ic_nav_normal'),
26 | iconSelected: $r('app.media.ic_nav_selected'),
27 | text: $r('app.string.bottom_text_nav')
28 | },
29 | {
30 | icon: $r('app.media.ic_project_normal'),
31 | iconSelected: $r('app.media.ic_project_selected'),
32 | text: $r('app.string.bottom_text_project')
33 | },
34 | {
35 | icon: $r('app.media.ic_msg_normal'),
36 | iconSelected: $r('app.media.ic_msg_selected'),
37 | text: $r('app.string.bottom_text_msg')
38 | },
39 | {
40 | icon: $r('app.media.ic_me_normal'),
41 | iconSelected: $r('app.media.ic_me_selected'),
42 | text: $r('app.string.bottom_text_me')
43 | }
44 | ]
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/HomeViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:1-home-数据逻辑类
3 | */
4 | import List from '@ohos.util.List';
5 | import HttpConfig from '../api/HttpConfig';
6 | import { articleListReq, articleTopReq, bannerReq } from '../api/HttpRequest';
7 | import ResponseResult from '../api/ResponseResult';
8 | import { Article, ArticleList, ArticleTop } from '../bean/ArticleBean';
9 | import { Banner } from '../bean/BannerBean';
10 | import Logger from '../utils/Logger';
11 | /**
12 | * @desc:HomePage对应数据处理类
13 | */
14 | class HomeViewModel {
15 | // bannerData: List
16 | // articleTopData: ArticleTop
17 | // articleListData: ArticleList
18 |
19 |
20 | //首页-banner轮播图、置顶文章、文章三个接口
21 | getHomeData() {
22 | return Promise.all([this.getBanner(), this.getArticleTop(), this.getArticle(0)])
23 | // .then(result => {
24 | // //1-result[0]-Banner
25 | // this.bannerData = result[0]
26 | // //2-result[1]-置顶文章
27 | // this.articleTopData = result[1]
28 | // //3-result[3] - 文章列表
29 | // this.articleListData = result[2]
30 | // })
31 | }
32 | //1-首页-Banner
33 | getBanner(): Promise {
34 | return new Promise(async (resolve: Function, reject: Function) => {
35 | bannerReq().then((data: ResponseResult) => {
36 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
37 | resolve(data.data);
38 | } else {
39 | Logger.error('getBanner failed', JSON.stringify(data));
40 | reject($r('app.string.page_none_msg'));
41 | }
42 | })
43 | })
44 | }
45 | //2-首页-置顶
46 | getArticleTop(): Promise {
47 | return new Promise(async (resolve: Function, reject: Function) => {
48 | articleTopReq().then((data: ResponseResult) => {
49 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
50 | resolve(data.data);
51 | } else {
52 | Logger.error('getArticleTop failed', JSON.stringify(data));
53 | reject($r('app.string.page_none_msg'));
54 | }
55 | })
56 | })
57 | }
58 | //3-首页-文章
59 | getArticle(page: number): Promise {
60 | return new Promise(async (resolve: Function, reject: Function) => {
61 | articleListReq(page).then((data: ResponseResult) => {
62 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
63 | resolve(data.data);
64 | } else {
65 | Logger.error('getArticle failed', JSON.stringify(data));
66 | reject($r('app.string.page_none_msg'));
67 | }
68 | })
69 | })
70 | }
71 | }
72 |
73 | let homeViewModel = new HomeViewModel();
74 |
75 | export default homeViewModel as HomeViewModel;
76 |
77 |
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/InfoViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * 积分排行或个人积分-数据类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { coinReq, rankReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { CoinData } from '../bean/CoinBean';
8 | import { RankData } from '../bean/RankBean';
9 | import Logger from '../utils/Logger';
10 |
11 | class InfoViewModel {
12 | //1-排行榜
13 | getRank(page: number): Promise {
14 | return new Promise(async (resolve: Function, reject: Function) => {
15 | rankReq(page).then((data: ResponseResult) => {
16 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
17 | resolve(data.data);
18 | } else {
19 | Logger.error('getRank failed', JSON.stringify(data));
20 | reject($r('app.string.page_none_msg'));
21 | }
22 | })
23 | })
24 | }
25 |
26 | //2-签到积分
27 | getCoin(page: number): Promise {
28 | return new Promise(async (resolve: Function, reject: Function) => {
29 | coinReq(page).then((data: ResponseResult) => {
30 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
31 | resolve(data.data);
32 | } else {
33 | Logger.error('getRank failed', JSON.stringify(data));
34 | reject($r('app.string.page_none_msg'));
35 | }
36 | })
37 | })
38 | }
39 | }
40 |
41 | let infoViewModel = new InfoViewModel();
42 |
43 | export default infoViewModel as InfoViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/LoginRegisterViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:5-登录、注册-数据逻辑类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { loginReq, registerReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { UserInfo } from '../bean/UserInfoBean';
8 | import Logger from '../utils/Logger';
9 |
10 |
11 | class LoginRegisterViewModel {
12 |
13 | //用户登录
14 | userLogin(username: string, password: string): Promise {
15 | return new Promise(async (resolve: Function, reject: Function) => {
16 | loginReq(username, password).then((data: ResponseResult) => {
17 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
18 | resolve(data);
19 | } else {
20 | Logger.error('userLogin failed', JSON.stringify(data));
21 | resolve(data);
22 | //reject($r('app.string.page_none_msg'));
23 | }
24 | })
25 | })
26 | }
27 | //用户注册
28 | userRegister(username: string, password: string, repassword: string): Promise {
29 | return new Promise(async (resolve: Function, reject: Function) => {
30 | registerReq(username, password, repassword).then((data: ResponseResult) => {
31 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
32 | resolve(data);
33 | } else {
34 | Logger.error('userRegister failed', JSON.stringify(data));
35 | resolve(data);
36 | //reject($r('app.string.page_none_msg'));
37 | }
38 | })
39 | })
40 | }
41 | }
42 |
43 | let loginRegisterViewModel = new LoginRegisterViewModel();
44 |
45 | export default loginRegisterViewModel as LoginRegisterViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/MeViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:5-Me-数据逻辑类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { userReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { UserData, UserInfo } from '../bean/UserInfoBean';
8 | import Logger from '../utils/Logger';
9 |
10 | class MeViewModel {
11 |
12 |
13 | //5-我的页面数据接口
14 | getUserInfo(): Promise {
15 | return new Promise(async (resolve: Function, reject: Function) => {
16 | userReq().then((data: ResponseResult) => {
17 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
18 | resolve(data.data);
19 | } else {
20 | Logger.error('getUserInfo failed', JSON.stringify(data));
21 | reject($r('app.string.page_none_msg'));
22 | }
23 | })
24 | })
25 | }
26 | }
27 |
28 | let meViewModel = new MeViewModel();
29 |
30 | export default meViewModel as MeViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/MsgViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:4-Msg-数据逻辑类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { msgReadReq, msgUnReadReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { MsgData } from '../bean/MsgBean';
8 | import Logger from '../utils/Logger';
9 |
10 | class MsgViewModel {
11 |
12 | //1-导航页面数据接口
13 |
14 | //未读消息
15 | getMsgUnRead(): Promise {
16 | return new Promise(async (resolve: Function, reject: Function) => {
17 | msgUnReadReq().then((data: ResponseResult) => {
18 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
19 | resolve(data.data);
20 | } else {
21 | Logger.error('getMsgUnRead failed', JSON.stringify(data));
22 | reject($r('app.string.page_none_msg'));
23 | }
24 | })
25 | })
26 | }
27 |
28 | //已读消息
29 | getMsgRead(page:number): Promise {
30 | return new Promise(async (resolve: Function, reject: Function) => {
31 | msgReadReq(page).then((data: ResponseResult) => {
32 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
33 | resolve(data.data);
34 | } else {
35 | Logger.error('getMsgUnRead failed', JSON.stringify(data));
36 | reject($r('app.string.page_none_msg'));
37 | }
38 | })
39 | })
40 | }
41 | }
42 |
43 | let msgViewModel = new MsgViewModel();
44 |
45 | export default msgViewModel as MsgViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/NavigatorModel.ets:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022 Huawei Device Co., Ltd.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 |
16 | /**
17 | * NewsData params info.
18 | */
19 | export class NavigatorModel {
20 | /**
21 | * Jumping Path.
22 | */
23 | path: Resource | string = '';
24 |
25 | /**
26 | * Prompt message.
27 | */
28 | title: Resource | string = '';
29 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/ProjectViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:3-Project-数据逻辑类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { projectListReq, projectReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { ArticleList } from '../bean/ArticleBean';
8 | import { ProjectData, ProjectItem } from '../bean/ProjectBean';
9 | import Logger from '../utils/Logger';
10 |
11 | class ProjectViewModel {
12 |
13 | //3-项目页面数据接口
14 |
15 | //项目分类
16 | getProject(): Promise {
17 | return new Promise(async (resolve: Function, reject: Function) => {
18 | projectReq().then((data: ResponseResult) => {
19 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
20 | resolve(data.data);
21 | } else {
22 | Logger.error('getProject failed', JSON.stringify(data));
23 | reject($r('app.string.page_none_msg'));
24 | }
25 | })
26 | })
27 | }
28 | //项目列表数据
29 | getProjectList(page: number, cid: number): Promise {
30 | return new Promise(async (resolve: Function, reject: Function) => {
31 | projectListReq(page = page, cid = cid).then((data: ResponseResult) => {
32 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
33 | resolve(data.data);
34 | } else {
35 | Logger.error('getProjectList failed', JSON.stringify(data));
36 | reject($r('app.string.page_none_msg'));
37 | }
38 | })
39 | })
40 | }
41 | }
42 |
43 | let projectViewModel = new ProjectViewModel();
44 |
45 | export default projectViewModel as ProjectViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/SettingViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:7-Setting-数据逻辑类
3 | */
4 | import router from '@ohos.router';
5 | import { logoutReq } from '../api/HttpRequest';
6 | import SettingItem from '../bean/SettingItem';
7 | import Constants from '../common/constants/Constants';
8 |
9 | class SettingViewModel {
10 | logout() {
11 | logoutReq().then(result => {
12 | //清除cookie等数据
13 | if (AppStorage.Has(Constants.Cookie)) {
14 | AppStorage.Set(Constants.Cookie, '')
15 | PersistentStorage.DeleteProp(Constants.Cookie)
16 | //AppStorage.Clear()
17 | //router.back()
18 | router.replaceUrl({ url: Constants.MainPage_Path });
19 | }
20 | })
21 | }
22 |
23 | /**
24 | * @desc:设置Items数据
25 | * @returns
26 | */
27 | getSettingListData(): Array {
28 | let settingListData: SettingItem[] = [
29 | new SettingItem($r('app.string.setting_list_theme'), $r('app.media.ic_theme'), $r(null)),
30 | new SettingItem($r('app.string.setting_list_language'), $r('app.media.ic_language'), $r(null)),
31 | new SettingItem($r('app.string.setting_list_about'), $r('app.media.ic_about'), $r(null)),
32 | ];
33 | return settingListData;
34 | }
35 | }
36 |
37 | let settingViewModel = new SettingViewModel();
38 |
39 | export default settingViewModel as SettingViewModel;
--------------------------------------------------------------------------------
/entry/src/main/ets/viewmodel/TreeViewModel.ets:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc:2-Nav-数据逻辑类
3 | */
4 | import HttpConfig from '../api/HttpConfig';
5 | import { treeListReq, treeReq } from '../api/HttpRequest';
6 | import ResponseResult from '../api/ResponseResult';
7 | import { TreeArticle, TreeData, TreeItem } from '../bean/TreeBean';
8 | import Logger from '../utils/Logger';
9 |
10 | class TreeViewModel {
11 |
12 | //2-Tree(导航)页面数据接口
13 |
14 | getTreeData(): Promise {
15 | return new Promise(async (resolve: Function, reject: Function) => {
16 | treeReq().then((data: ResponseResult) => {
17 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
18 | resolve(data.data);
19 | } else {
20 | Logger.error('getTreeData failed', JSON.stringify(data));
21 | reject($r('app.string.page_none_msg'));
22 | }
23 | })
24 | })
25 | }
26 | //2-知识体系下的文章
27 | getTreeArticleList(page: number, cid: number): Promise {
28 | return new Promise(async (resolve: Function, reject: Function) => {
29 | treeListReq(page = page, cid = cid).then((data: ResponseResult) => {
30 | if (data.errorCode === HttpConfig.SERVER_CODE_SUCCESS) {
31 | resolve(data.data);
32 | } else {
33 | Logger.error('getTreeArticleList failed', JSON.stringify(data));
34 | reject($r('app.string.page_none_msg'));
35 | }
36 | })
37 | })
38 | }
39 | }
40 |
41 | let treeViewModel = new TreeViewModel();
42 |
43 | export default treeViewModel as TreeViewModel;
--------------------------------------------------------------------------------
/entry/src/main/module.json5:
--------------------------------------------------------------------------------
1 | {
2 | "module": {
3 | "name": "entry",
4 | "type": "entry",
5 | "description": "$string:module_desc",
6 | "mainElement": "EntryAbility",
7 | "deviceTypes": [
8 | "phone",
9 | "tablet"
10 | ],
11 | "deliveryWithInstall": true,
12 | "installationFree": false,
13 |
14 | "pages": "$profile:main_pages",
15 | "abilities": [
16 | {
17 | "name": "EntryAbility",
18 | "srcEntry": "./ets/entryability/EntryAbility.ets",
19 | "description": "$string:EntryAbility_desc",
20 | "icon": "$media:ic_logo",
21 | "label": "$string:EntryAbility_label",
22 | "startWindowIcon": "$media:ic_logo",
23 | "startWindowBackground": "$color:start_window_background",
24 | "exported": true,
25 | "skills": [
26 | {
27 | "entities": [
28 | "entity.system.home"
29 | ],
30 | "actions": [
31 | "action.system.home"
32 | ]
33 | }
34 | ]
35 | }
36 | ],
37 | "requestPermissions": [
38 | {
39 | "name": "ohos.permission.INTERNET",
40 | "usedScene": {
41 | "when": "always"
42 | }
43 | }
44 | ]
45 | }
46 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/color.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": [
3 | {
4 | "name": "start_window_background",
5 | "value": "#FFFFFF"
6 | },
7 | {
8 | "name": "bottom_tabs_font_color_selected",
9 | "value": "#007DFF"
10 | },
11 | {
12 | "name": "color_border",
13 | "value": "#FF182431"
14 | },
15 | {
16 | "name": "bottom_tabs_background_color",
17 | "value": "#F1F3F5"
18 | },
19 | {
20 | "name": "bottom_tabs_font_color",
21 | "value": "#000000"
22 | },
23 | {
24 | "name": "light_pink",
25 | "value": "#FFB6C1"
26 | },
27 | {
28 | "name": "pink",
29 | "value": "#FFC0CB"
30 | },
31 | {
32 | "name": "crimson",
33 | "value": "#DC143C"
34 | },
35 | {
36 | "name": "lavender_blush",
37 | "value": "#FF0F50"
38 | },
39 | {
40 | "name": "paleViolet_red",
41 | "value": "#DB7093"
42 | },
43 | {
44 | "name": "hot_pink",
45 | "value": "#FF69B4"
46 | },
47 | {
48 | "name": "deep_pink",
49 | "value": "#FF1493"
50 | },
51 | {
52 | "name": "medium_violet_red",
53 | "value": "#C71585"
54 | },
55 | {
56 | "name": "orchid",
57 | "value": "#DA70D6"
58 | },
59 | {
60 | "name": "thistle",
61 | "value": "#D8BFD8"
62 | },
63 | {
64 | "name": "plum",
65 | "value": "#DDA0DD"
66 | },
67 | {
68 | "name": "violet",
69 | "value": "#EE82EE"
70 | },
71 | {
72 | "name": "magenta",
73 | "value": "#FF00FF"
74 | },
75 | {
76 | "name": "fuchsia",
77 | "value": "#FF00FF"
78 | },
79 | {
80 | "name": "dark_magenta",
81 | "value": "#8B008B"
82 | },
83 | {
84 | "name": "purple",
85 | "value": "#800080"
86 | },
87 | {
88 | "name": "medium_orchid",
89 | "value": "#BA55D3"
90 | },
91 | {
92 | "name": "dark_violet",
93 | "value": "#9400D3"
94 | },
95 | {
96 | "name": "dark_orchid",
97 | "value": "#9932CC"
98 | },
99 | {
100 | "name": "indigo",
101 | "value": "#4B0082"
102 | },
103 | {
104 | "name": "blue_violet",
105 | "value": "#8A2BE2"
106 | },
107 | {
108 | "name": "medium_purple",
109 | "value": "#9370DB"
110 | },
111 | {
112 | "name": "medium_slate_blue",
113 | "value": "#7B68EE"
114 | },
115 | {
116 | "name": "slate_blue",
117 | "value": "#6A5ACD"
118 | },
119 | {
120 | "name": "dark_slate_blue",
121 | "value": "#483D8B"
122 | },
123 | {
124 | "name": "lavender",
125 | "value": "#E6E6FA"
126 | },
127 | {
128 | "name": "ghost_white",
129 | "value": "#F8F8FF"
130 | },
131 | {
132 | "name": "blue",
133 | "value": "#0000FF"
134 | },
135 | {
136 | "name": "indigo_blue",
137 | "value": "#0000FF"
138 | },
139 | {
140 | "name": "medium_blue",
141 | "value": "#0000CD"
142 | },
143 | {
144 | "name": "midnight_blue",
145 | "value": "#191970"
146 | },
147 | {
148 | "name": "dark_blue",
149 | "value": "#00008B"
150 | },
151 | {
152 | "name": "navy",
153 | "value": "#000080"
154 | },
155 | {
156 | "name": "royal_blue",
157 | "value": "#4169E1"
158 | },
159 | {
160 | "name": "cornflower_blue",
161 | "value": "#6495ED"
162 | },
163 | {
164 | "name": "light_steel_blue",
165 | "value": "#B0C4DE"
166 | },
167 | {
168 | "name": "light_slate_gray",
169 | "value": "#778899"
170 | },
171 | {
172 | "name": "slate_gray",
173 | "value": "#708090"
174 | },
175 | {
176 | "name": "dodger_blue",
177 | "value": "#1E90FF"
178 | },
179 | {
180 | "name": "steel_blue",
181 | "value": "#4682B4"
182 | },
183 | {
184 | "name": "light_sky_blue",
185 | "value": "#87CEFA"
186 | },
187 | {
188 | "name": "sky_blue",
189 | "value": "#87CEEB"
190 | },
191 | {
192 | "name": "deep_sky_blue",
193 | "value": "#00BFFF"
194 | },
195 | {
196 | "name": "light_blue",
197 | "value": "#ADD8E6"
198 | },
199 | {
200 | "name": "powder_blue",
201 | "value": "#B0E0E6"
202 | },
203 | {
204 | "name": "cadet_blue",
205 | "value": "#5F9EA0"
206 | },
207 | {
208 | "name": "azure",
209 | "value": "#F0FFFF"
210 | },
211 | {
212 | "name": "light_cyan",
213 | "value": "#E1FFFF"
214 | },
215 | {
216 | "name": "pale_turquoise",
217 | "value": "#AFEEEE"
218 | },
219 | {
220 | "name": "cyan",
221 | "value": "#00FFFF"
222 | },
223 | {
224 | "name": "aqua",
225 | "value": "#00FFFF"
226 | },
227 | {
228 | "name": "dark_turquoise",
229 | "value": "#00CED1"
230 | },
231 | {
232 | "name": "dark_slate_gray",
233 | "value": "#2F4F4F"
234 | },
235 | {
236 | "name": "dark_cyan",
237 | "value": "#008B8B"
238 | },
239 | {
240 | "name": "teal",
241 | "value": "#008080"
242 | },
243 | {
244 | "name": "medium_turquoise",
245 | "value": "#48D1CC"
246 | },
247 | {
248 | "name": "light_sea_green",
249 | "value": "#20B2AA"
250 | },
251 | {
252 | "name": "turquoise",
253 | "value": "#40E0D0"
254 | },
255 | {
256 | "name": "auqamarin",
257 | "value": "#7FFFAA"
258 | },
259 | {
260 | "name": "medium_aquamarine",
261 | "value": "#00FA9A"
262 | },
263 | {
264 | "name": "medium_spring_green",
265 | "value": "#00FF7F"
266 | },
267 | {
268 | "name": "mint_cream",
269 | "value": "#F5FFFA"
270 | },
271 | {
272 | "name": "spring_green",
273 | "value": "#3CB371"
274 | },
275 | {
276 | "name": "sea_green",
277 | "value": "#2E8B57"
278 | },
279 | {
280 | "name": "honeydew",
281 | "value": "#F0FFF0"
282 | },
283 | {
284 | "name": "light_green",
285 | "value": "#90EE90"
286 | },
287 | {
288 | "name": "pale_green",
289 | "value": "#98FB98"
290 | },
291 | {
292 | "name": "dark_sea_green",
293 | "value": "#8FBC8F"
294 | },
295 | {
296 | "name": "lime_green",
297 | "value": "#32CD32"
298 | },
299 | {
300 | "name": "lime",
301 | "value": "#00FF00"
302 | },
303 | {
304 | "name": "forest_green",
305 | "value": "#228B22"
306 | },
307 | {
308 | "name": "green",
309 | "value": "#008000"
310 | },
311 | {
312 | "name": "dark_green",
313 | "value": "#006400"
314 | },
315 | {
316 | "name": "chartreuse",
317 | "value": "#7FFF00"
318 | },
319 | {
320 | "name": "lawn_green",
321 | "value": "#7CFC00"
322 | },
323 | {
324 | "name": "green_yellow",
325 | "value": "#ADFF2F"
326 | },
327 | {
328 | "name": "olive_drab",
329 | "value": "#556B2F"
330 | },
331 | {
332 | "name": "beige",
333 | "value": "#F5F5DC"
334 | },
335 | {
336 | "name": "light_goldenrod_yellow",
337 | "value": "#FAFAD2"
338 | },
339 | {
340 | "name": "ivory",
341 | "value": "#FFFFF0"
342 | },
343 | {
344 | "name": "light_yellow",
345 | "value": "#FFFFE0"
346 | },
347 | {
348 | "name": "yellow",
349 | "value": "#FFFF00"
350 | },
351 | {
352 | "name": "olive",
353 | "value": "#808000"
354 | },
355 | {
356 | "name": "dark_khaki",
357 | "value": "#BDB76B"
358 | },
359 | {
360 | "name": "lemon_chiffon",
361 | "value": "#FFFACD"
362 | },
363 | {
364 | "name": "pale_godenrod",
365 | "value": "#EEE8AA"
366 | },
367 | {
368 | "name": "khaki",
369 | "value": "#F0E68C"
370 | },
371 | {
372 | "name": "gold",
373 | "value": "#FFD700"
374 | },
375 | {
376 | "name": "cornislk",
377 | "value": "#FFF8DC"
378 | },
379 | {
380 | "name": "gold_enrod",
381 | "value": "#DAA520"
382 | },
383 | {
384 | "name": "floral_white",
385 | "value": "#FFFAF0"
386 | },
387 | {
388 | "name": "oldLace",
389 | "value": "#FDF5E6"
390 | },
391 | {
392 | "name": "wheat",
393 | "value": "#F5DEB3"
394 | },
395 | {
396 | "name": "moccasin",
397 | "value": "#FFE4B5"
398 | },
399 | {
400 | "name": "orange",
401 | "value": "#FFA500"
402 | },
403 | {
404 | "name": "papaya_whip",
405 | "value": "#FFEFD5"
406 | },
407 | {
408 | "name": "blanched_almond",
409 | "value": "#FFEBCD"
410 | },
411 | {
412 | "name": "navajo_white",
413 | "value": "#FFDEAD"
414 | },
415 | {
416 | "name": "antique_white",
417 | "value": "#FAEBD7"
418 | },
419 | {
420 | "name": "tan",
421 | "value": "#D2B48C"
422 | },
423 | {
424 | "name": "bruly_wood",
425 | "value": "#DEB887"
426 | },
427 | {
428 | "name": "bisque",
429 | "value": "#FFE4C4"
430 | },
431 | {
432 | "name": "dark_orange",
433 | "value": "#FF8C00"
434 | },
435 | {
436 | "name": "linen",
437 | "value": "#FAF0E6"
438 | },
439 | {
440 | "name": "peru",
441 | "value": "#CD853F"
442 | },
443 | {
444 | "name": "peach_puff",
445 | "value": "#FFDAB9"
446 | },
447 | {
448 | "name": "sandy_brown",
449 | "value": "#F4A460"
450 | },
451 | {
452 | "name": "chocolate",
453 | "value": "#D2691E"
454 | },
455 | {
456 | "name": "saddle_brown",
457 | "value": "#8B4513"
458 | },
459 | {
460 | "name": "sea_shell",
461 | "value": "#FFF5EE"
462 | },
463 | {
464 | "name": "sienna",
465 | "value": "#A0522D"
466 | },
467 | {
468 | "name": "light_salmon",
469 | "value": "#FFA07A"
470 | },
471 | {
472 | "name": "coral",
473 | "value": "#FF7F50"
474 | },
475 | {
476 | "name": "orange_red",
477 | "value": "#FF4500"
478 | },
479 | {
480 | "name": "dark_salmon",
481 | "value": "#E9967A"
482 | },
483 | {
484 | "name": "tomato",
485 | "value": "#FF6347"
486 | },
487 | {
488 | "name": "misty_rose",
489 | "value": "#FFE4E1"
490 | },
491 | {
492 | "name": "salmon",
493 | "value": "#FA8072"
494 | },
495 | {
496 | "name": "snow",
497 | "value": "#FFFAFA"
498 | },
499 | {
500 | "name": "light_coral",
501 | "value": "#FFFAFA"
502 | },
503 | {
504 | "name": "rosy_brown",
505 | "value": "#BC8F8F"
506 | },
507 | {
508 | "name": "indian_red",
509 | "value": "#CD5C5C"
510 | },
511 | {
512 | "name": "red",
513 | "value": "#FF0000"
514 | },
515 | {
516 | "name": "brown",
517 | "value": "#A52A2A"
518 | },
519 | {
520 | "name": "fire_brick",
521 | "value": "#B22222"
522 | },
523 | {
524 | "name": "dark_red",
525 | "value": "#8B0000"
526 | },
527 | {
528 | "name": "maroon",
529 | "value": "#800000"
530 | },
531 | {
532 | "name": "white",
533 | "value": "#FFFFFF"
534 | },
535 | {
536 | "name": "white_smoke",
537 | "value": "#F5F5F5"
538 | },
539 | {
540 | "name": "gainsboro",
541 | "value": "#DCDCDC"
542 | },
543 | {
544 | "name": "light_gray",
545 | "value": "#D3D3D3"
546 | },
547 | {
548 | "name": "silver",
549 | "value": "#C0C0C0"
550 | },
551 | {
552 | "name": "dark_gray",
553 | "value": "#A9A9A9"
554 | },
555 | {
556 | "name": "gray",
557 | "value": "#808080"
558 | },
559 | {
560 | "name": "dim_gray",
561 | "value": "#696969"
562 | },
563 | {
564 | "name": "black",
565 | "value": "#000000"
566 | }
567 | ]
568 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/float.json:
--------------------------------------------------------------------------------
1 | {
2 | "float": [
3 | {
4 | "name": "bottom_font_size",
5 | "value": "10fp"
6 | },
7 | {
8 | "name": "font_size_24fp",
9 | "value": "24fp"
10 | },
11 | {
12 | "name": "font_size_16fp",
13 | "value": "16fp"
14 | },
15 | {
16 | "name": "1fp",
17 | "value": "1fp"
18 | },
19 | {
20 | "name": "2fp",
21 | "value": "2fp"
22 | },
23 | {
24 | "name": "3fp",
25 | "value": "3fp"
26 | },
27 | {
28 | "name": "4fp",
29 | "value": "4fp"
30 | },
31 | {
32 | "name": "5fp",
33 | "value": "5fp"
34 | },
35 | {
36 | "name": "6fp",
37 | "value": "6fp"
38 | },
39 | {
40 | "name": "7fp",
41 | "value": "7fp"
42 | },
43 | {
44 | "name": "8fp",
45 | "value": "8fp"
46 | },
47 | {
48 | "name": "9fp",
49 | "value": "9fp"
50 | },
51 | {
52 | "name": "10fp",
53 | "value": "10fp"
54 | },
55 | {
56 | "name": "11fp",
57 | "value": "11fp"
58 | },
59 | {
60 | "name": "12fp",
61 | "value": "12fp"
62 | },
63 | {
64 | "name": "13fp",
65 | "value": "13fp"
66 | },
67 | {
68 | "name": "14fp",
69 | "value": "14fp"
70 | },
71 | {
72 | "name": "15fp",
73 | "value": "15fp"
74 | },
75 | {
76 | "name": "16fp",
77 | "value": "16fp"
78 | },
79 | {
80 | "name": "17fp",
81 | "value": "17fp"
82 | },
83 | {
84 | "name": "18fp",
85 | "value": "18fp"
86 | },
87 | {
88 | "name": "19fp",
89 | "value": "19fp"
90 | },
91 | {
92 | "name": "20fp",
93 | "value": "20fp"
94 | },
95 | {
96 | "name": "21fp",
97 | "value": "21fp"
98 | },
99 | {
100 | "name": "22fp",
101 | "value": "22fp"
102 | },
103 | {
104 | "name": "23fp",
105 | "value": "23fp"
106 | },
107 | {
108 | "name": "24fp",
109 | "value": "24fp"
110 | },
111 | {
112 | "name": "25fp",
113 | "value": "25fp"
114 | },
115 | {
116 | "name": "1vp",
117 | "value": "1vp"
118 | },
119 | {
120 | "name": "2vp",
121 | "value": "2vp"
122 | },
123 | {
124 | "name": "3vp",
125 | "value": "3vp"
126 | },
127 | {
128 | "name": "4vp",
129 | "value": "4vp"
130 | },
131 | {
132 | "name": "5vp",
133 | "value": "5vp"
134 | },
135 | {
136 | "name": "6vp",
137 | "value": "6vp"
138 | },
139 | {
140 | "name": "7vp",
141 | "value": "7vp"
142 | },
143 | {
144 | "name": "8vp",
145 | "value": "8vp"
146 | },
147 | {
148 | "name": "9vp",
149 | "value": "9vp"
150 | },
151 | {
152 | "name": "10vp",
153 | "value": "10vp"
154 | },
155 | {
156 | "name": "11vp",
157 | "value": "11vp"
158 | },
159 | {
160 | "name": "12vp",
161 | "value": "12vp"
162 | },
163 | {
164 | "name": "13vp",
165 | "value": "13vp"
166 | },
167 | {
168 | "name": "14vp",
169 | "value": "14vp"
170 | },
171 | {
172 | "name": "15vp",
173 | "value": "15vp"
174 | },
175 | {
176 | "name": "16vp",
177 | "value": "16vp"
178 | },
179 | {
180 | "name": "17vp",
181 | "value": "17vp"
182 | },
183 | {
184 | "name": "18vp",
185 | "value": "18vp"
186 | },
187 | {
188 | "name": "19vp",
189 | "value": "19vp"
190 | },
191 | {
192 | "name": "20vp",
193 | "value": "20vp"
194 | },
195 | {
196 | "name": "21vp",
197 | "value": "21vp"
198 | },
199 | {
200 | "name": "22vp",
201 | "value": "22vp"
202 | },
203 | {
204 | "name": "23vp",
205 | "value": "24vp"
206 | },
207 | {
208 | "name": "24vp",
209 | "value": "24vp"
210 | },
211 | {
212 | "name": "25vp",
213 | "value": "25vp"
214 | },
215 | {
216 | "name": "26vp",
217 | "value": "26vp"
218 | },
219 | {
220 | "name": "27vp",
221 | "value": "27vp"
222 | },
223 | {
224 | "name": "28vp",
225 | "value": "28vp"
226 | },
227 | {
228 | "name": "29vp",
229 | "value": "29vp"
230 | },
231 | {
232 | "name": "30vp",
233 | "value": "30vp"
234 | },
235 | {
236 | "name": "40vp",
237 | "value": "40vp"
238 | },
239 | {
240 | "name": "41vp",
241 | "value": "41vp"
242 | },
243 | {
244 | "name": "42vp",
245 | "value": "42vp"
246 | },
247 | {
248 | "name": "43vp",
249 | "value": "43vp"
250 | },
251 | {
252 | "name": "44vp",
253 | "value": "44vp"
254 | },
255 | {
256 | "name": "45vp",
257 | "value": "45vp"
258 | },
259 | {
260 | "name": "46vp",
261 | "value": "46vp"
262 | },
263 | {
264 | "name": "47vp",
265 | "value": "47vp"
266 | },
267 | {
268 | "name": "48vp",
269 | "value": "48vp"
270 | },
271 | {
272 | "name": "50vp",
273 | "value": "50vp"
274 | },
275 | {
276 | "name": "60vp",
277 | "value": "60vp"
278 | },
279 | {
280 | "name": "70vp",
281 | "value": "70vp"
282 | },
283 | {
284 | "name": "80vp",
285 | "value": "80vp"
286 | },
287 | {
288 | "name": "81vp",
289 | "value": "81vp"
290 | },
291 | {
292 | "name": "82vp",
293 | "value": "82vp"
294 | },
295 | {
296 | "name": "83vp",
297 | "value": "83vp"
298 | },
299 | {
300 | "name": "84vp",
301 | "value": "84vp"
302 | },
303 | {
304 | "name": "85vp",
305 | "value": "85vp"
306 | },
307 | {
308 | "name": "86vp",
309 | "value": "86vp"
310 | },
311 | {
312 | "name": "87vp",
313 | "value": "87vp"
314 | },
315 | {
316 | "name": "88vp",
317 | "value": "88vp"
318 | },
319 | {
320 | "name": "89vp",
321 | "value": "89vp"
322 | },
323 | {
324 | "name": "90vp",
325 | "value": "90vp"
326 | },
327 | {
328 | "name": "100vp",
329 | "value": "100vp"
330 | },
331 | {
332 | "name": "110vp",
333 | "value": "110vp"
334 | },
335 | {
336 | "name": "120vp",
337 | "value": "120vp"
338 | },
339 | {
340 | "name": "130vp",
341 | "value": "130vp"
342 | },
343 | {
344 | "name": "140vp",
345 | "value": "140vp"
346 | },
347 | {
348 | "name": "150vp",
349 | "value": "150vp"
350 | },
351 | {
352 | "name": "192vp",
353 | "value": "192vp"
354 | }
355 | ]
356 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "module description"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "WanAndroidHM"
14 | },
15 | {
16 | "name": "bottom_text_home",
17 | "value": "首页"
18 | },
19 | {
20 | "name": "bottom_text_nav",
21 | "value": "导航"
22 | },
23 | {
24 | "name": "bottom_text_project",
25 | "value": "项目"
26 | },
27 | {
28 | "name": "bottom_text_msg",
29 | "value": "消息"
30 | },
31 | {
32 | "name": "bottom_text_me",
33 | "value": "我的"
34 | },
35 | {
36 | "name": "http_error_message",
37 | "value": "网络请求失败,请稍后尝试!"
38 | },
39 | {
40 | "name": "page_none_msg",
41 | "value": "网络加载失败"
42 | },
43 | {
44 | "name": "input_empty_tips",
45 | "value": "输入不能为空"
46 | },
47 | {
48 | "name": "login_page",
49 | "value": "登录界面"
50 | },
51 | {
52 | "name": "register_page",
53 | "value": "注册界面"
54 | },
55 | {
56 | "name": "login_more",
57 | "value": "登录帐号以使用更多服务"
58 | },
59 | {
60 | "name": "register_more",
61 | "value": "注册帐号以使用更多服务"
62 | },
63 | {
64 | "name": "account",
65 | "value": "帐号"
66 | },
67 | {
68 | "name": "password",
69 | "value": "密码"
70 | },
71 | {
72 | "name": "repassword",
73 | "value": "确认密码"
74 | },
75 | {
76 | "name": "login",
77 | "value": "登录"
78 | },
79 | {
80 | "name": "register",
81 | "value": "注册"
82 | },
83 | {
84 | "name": "register_account",
85 | "value": "没有账号,去注册"
86 | },
87 | {
88 | "name": "login_account",
89 | "value": "已有账号,去登录"
90 | },
91 | {
92 | "name": "internet_err",
93 | "value": "网络加载失败!"
94 | },
95 | {
96 | "name": "setting_list_theme",
97 | "value": "主题"
98 | },
99 | {
100 | "name": "setting_list_language",
101 | "value": "语言"
102 | },
103 | {
104 | "name": "setting_list_about",
105 | "value": "关于"
106 | },
107 | {
108 | "name": "no_more_data",
109 | "value": "没有更多数据了"
110 | }
111 | ]
112 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_about.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_arrow_left.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_arrow_right.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_clock.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_home_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_home_normal.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_home_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_home_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_language.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_language.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_logo.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_me_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_me_normal.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_me_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_me_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_msg_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_msg_normal.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_msg_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_msg_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_nav_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_nav_normal.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_nav_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_nav_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_project_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_project_normal.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_project_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_project_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_setting.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_theme.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/ic_user.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/icon.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/splash_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/main/resources/base/media/splash_bg.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/profile/main_pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": [
3 | "pages/Splash",
4 | "pages/MainPage",
5 | "pages/LoginRegisterPage",
6 | "pages/WebPage",
7 | "pages/SettingPage",
8 | "pages/TreeTabPage",
9 | "pages/InfoPage"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/entry/src/main/resources/en_US/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "module description"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "WanAndroidHM"
14 | },
15 | {
16 | "name": "bottom_text_home",
17 | "value": "Home"
18 | },
19 | {
20 | "name": "bottom_text_nav",
21 | "value": "Nav"
22 | },
23 | {
24 | "name": "bottom_text_project",
25 | "value": "Project"
26 | },
27 | {
28 | "name": "bottom_text_msg",
29 | "value": "Msg"
30 | },
31 | {
32 | "name": "bottom_text_me",
33 | "value": "Me"
34 | },
35 | {
36 | "name": "http_error_message",
37 | "value": "Network request failed, please try later!"
38 | },
39 | {
40 | "name": "page_none_msg",
41 | "value": "Network loading failure"
42 | },
43 | {
44 | "name": "input_empty_tips",
45 | "value": "The input cannot be empty."
46 | },
47 | {
48 | "name": "login_page",
49 | "value": "Login page"
50 | },
51 | {
52 | "name": "register_page",
53 | "value": "register page"
54 | },
55 | {
56 | "name": "login_more",
57 | "value": "Log in to your account to use more services"
58 | },
59 | {
60 | "name": "register_more",
61 | "value": "register to your account to use more services"
62 | },
63 | {
64 | "name": "account",
65 | "value": "Account"
66 | },
67 | {
68 | "name": "password",
69 | "value": "Password"
70 | },
71 | {
72 | "name": "repassword",
73 | "value": "repassword"
74 | },
75 | {
76 | "name": "login",
77 | "value": "Log in"
78 | },
79 | {
80 | "name": "register",
81 | "value": "register"
82 | },
83 | {
84 | "name": "register_account",
85 | "value": "Registering an Account"
86 | },
87 | {
88 | "name": "login_account",
89 | "value": "login an Account"
90 | },
91 | {
92 | "name": "internet_err",
93 | "value": "Failed to load the network."
94 | },
95 | {
96 | "name": "setting_list_theme",
97 | "value": "Theme"
98 | },
99 | {
100 | "name": "setting_list_language",
101 | "value": "Language"
102 | },
103 | {
104 | "name": "setting_list_about",
105 | "value": "About"
106 | },
107 | {
108 | "name": "no_more_data",
109 | "value": "No More Data"
110 | }
111 | ]
112 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/zh_CN/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "模块描述"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "WanAndroidHM"
14 | },
15 | {
16 | "name": "bottom_text_home",
17 | "value": "首页"
18 | },
19 | {
20 | "name": "bottom_text_nav",
21 | "value": "导航"
22 | },
23 | {
24 | "name": "bottom_text_project",
25 | "value": "项目"
26 | },
27 | {
28 | "name": "bottom_text_msg",
29 | "value": "消息"
30 | },
31 | {
32 | "name": "bottom_text_me",
33 | "value": "我的"
34 | },
35 | {
36 | "name": "http_error_message",
37 | "value": "网络请求失败,请稍后尝试!"
38 | },
39 | {
40 | "name": "page_none_msg",
41 | "value": "网络加载失败"
42 | },
43 | {
44 | "name": "input_empty_tips",
45 | "value": "输入不能为空"
46 | },
47 | {
48 | "name": "login_page",
49 | "value": "登录界面"
50 | },
51 | {
52 | "name": "register_page",
53 | "value": "注册界面"
54 | },
55 | {
56 | "name": "login_more",
57 | "value": "登录帐号以使用更多服务"
58 | },
59 | {
60 | "name": "register_more",
61 | "value": "注册帐号以使用更多服务"
62 | },
63 | {
64 | "name": "account",
65 | "value": "帐号"
66 | },
67 | {
68 | "name": "password",
69 | "value": "密码"
70 | },
71 | {
72 | "name": "repassword",
73 | "value": "确认密码"
74 | },
75 | {
76 | "name": "login",
77 | "value": "登录"
78 | },
79 | {
80 | "name": "register",
81 | "value": "注册"
82 | },
83 | {
84 | "name": "register_account",
85 | "value": "没有账号,去注册"
86 | },
87 | {
88 | "name": "login_account",
89 | "value": "已有账号,去登录"
90 | },
91 | {
92 | "name": "internet_err",
93 | "value": "网络加载失败!"
94 | },
95 | {
96 | "name": "setting_list_theme",
97 | "value": "主题"
98 | },
99 | {
100 | "name": "setting_list_language",
101 | "value": "语言"
102 | },
103 | {
104 | "name": "setting_list_about",
105 | "value": "关于"
106 | },
107 | {
108 | "name": "no_more_data",
109 | "value": "没有更多数据了"
110 | }
111 | ]
112 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/test/Ability.test.ets:
--------------------------------------------------------------------------------
1 | import hilog from '@ohos.hilog';
2 | import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
3 |
4 | export default function abilityTest() {
5 | describe('ActsAbilityTest', function () {
6 | // Defines a test suite. Two parameters are supported: test suite name and test suite function.
7 | beforeAll(function () {
8 | // Presets an action, which is performed only once before all test cases of the test suite start.
9 | // This API supports only one parameter: preset action function.
10 | })
11 | beforeEach(function () {
12 | // Presets an action, which is performed before each unit test case starts.
13 | // The number of execution times is the same as the number of test cases defined by **it**.
14 | // This API supports only one parameter: preset action function.
15 | })
16 | afterEach(function () {
17 | // Presets a clear action, which is performed after each unit test case ends.
18 | // The number of execution times is the same as the number of test cases defined by **it**.
19 | // This API supports only one parameter: clear action function.
20 | })
21 | afterAll(function () {
22 | // Presets a clear action, which is performed after all test cases of the test suite end.
23 | // This API supports only one parameter: clear action function.
24 | })
25 | it('assertContain',0, function () {
26 | // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
27 | hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
28 | let a = 'abc'
29 | let b = 'b'
30 | // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
31 | expect(a).assertContain(b)
32 | expect(a).assertEqual(a)
33 | })
34 | })
35 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/test/List.test.ets:
--------------------------------------------------------------------------------
1 | import abilityTest from './Ability.test'
2 |
3 | export default function testsuite() {
4 | abilityTest()
5 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/testability/TestAbility.ets:
--------------------------------------------------------------------------------
1 | import UIAbility from '@ohos.app.ability.UIAbility';
2 | import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
3 | import hilog from '@ohos.hilog';
4 | import { Hypium } from '@ohos/hypium';
5 | import testsuite from '../test/List.test';
6 | import window from '@ohos.window';
7 |
8 | export default class TestAbility extends UIAbility {
9 | onCreate(want, launchParam) {
10 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
11 | hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
12 | hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? '');
13 | var abilityDelegator: any
14 | abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
15 | var abilityDelegatorArguments: any
16 | abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
17 | hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
18 | Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
19 | }
20 |
21 | onDestroy() {
22 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
23 | }
24 |
25 | onWindowStageCreate(windowStage: window.WindowStage) {
26 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
27 | windowStage.loadContent('testability/pages/Index', (err, data) => {
28 | if (err.code) {
29 | hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
30 | return;
31 | }
32 | hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
33 | JSON.stringify(data) ?? '');
34 | });
35 | }
36 |
37 | onWindowStageDestroy() {
38 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
39 | }
40 |
41 | onForeground() {
42 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
43 | }
44 |
45 | onBackground() {
46 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
47 | }
48 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/testability/pages/Index.ets:
--------------------------------------------------------------------------------
1 | import hilog from '@ohos.hilog';
2 |
3 | @Entry
4 | @Component
5 | struct Index {
6 | aboutToAppear() {
7 | hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
8 | }
9 | @State message: string = 'Hello World'
10 | build() {
11 | Row() {
12 | Column() {
13 | Text(this.message)
14 | .fontSize(50)
15 | .fontWeight(FontWeight.Bold)
16 | Button() {
17 | Text('next page')
18 | .fontSize(20)
19 | .fontWeight(FontWeight.Bold)
20 | }.type(ButtonType.Capsule)
21 | .margin({
22 | top: 20
23 | })
24 | .backgroundColor('#0D9FFB')
25 | .width('35%')
26 | .height('5%')
27 | .onClick(()=>{
28 | })
29 | }
30 | .width('100%')
31 | }
32 | .height('100%')
33 | }
34 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts:
--------------------------------------------------------------------------------
1 | import hilog from '@ohos.hilog';
2 | import TestRunner from '@ohos.application.testRunner';
3 | import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
4 |
5 | var abilityDelegator = undefined
6 | var abilityDelegatorArguments = undefined
7 |
8 | async function onAbilityCreateCallback() {
9 | hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
10 | }
11 |
12 | async function addAbilityMonitorCallback(err: any) {
13 | hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
14 | }
15 |
16 | export default class OpenHarmonyTestRunner implements TestRunner {
17 | constructor() {
18 | }
19 |
20 | onPrepare() {
21 | hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
22 | }
23 |
24 | async onRun() {
25 | hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
26 | abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
27 | abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
28 | var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
29 | let lMonitor = {
30 | abilityName: testAbilityName,
31 | onAbilityCreate: onAbilityCreateCallback,
32 | };
33 | abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
34 | var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
35 | var debug = abilityDelegatorArguments.parameters['-D']
36 | if (debug == 'true')
37 | {
38 | cmd += ' -D'
39 | }
40 | hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
41 | abilityDelegator.executeShellCommand(cmd,
42 | (err: any, d: any) => {
43 | hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
44 | hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
45 | hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
46 | })
47 | hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
48 | }
49 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/module.json5:
--------------------------------------------------------------------------------
1 | {
2 | "module": {
3 | "name": "entry_test",
4 | "type": "feature",
5 | "description": "$string:module_test_desc",
6 | "mainElement": "TestAbility",
7 | "deviceTypes": [
8 | "phone",
9 | "tablet"
10 | ],
11 | "deliveryWithInstall": true,
12 | "installationFree": false,
13 | "pages": "$profile:test_pages",
14 | "abilities": [
15 | {
16 | "name": "TestAbility",
17 | "srcEntry": "./ets/testability/TestAbility.ets",
18 | "description": "$string:TestAbility_desc",
19 | "icon": "$media:icon",
20 | "label": "$string:TestAbility_label",
21 | "exported": true,
22 | "startWindowIcon": "$media:icon",
23 | "startWindowBackground": "$color:start_window_background",
24 | "skills": [
25 | {
26 | "actions": [
27 | "action.system.home"
28 | ],
29 | "entities": [
30 | "entity.system.home"
31 | ]
32 | }
33 | ]
34 | }
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/entry/src/ohosTest/resources/base/element/color.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": [
3 | {
4 | "name": "start_window_background",
5 | "value": "#FFFFFF"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/resources/base/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_test_desc",
5 | "value": "test ability description"
6 | },
7 | {
8 | "name": "TestAbility_desc",
9 | "value": "the test ability"
10 | },
11 | {
12 | "name": "TestAbility_label",
13 | "value": "test label"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/resources/base/media/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/entry/src/ohosTest/resources/base/media/icon.png
--------------------------------------------------------------------------------
/entry/src/ohosTest/resources/base/profile/test_pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": [
3 | "testability/pages/Index"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/hvigor/hvigor-config.json5:
--------------------------------------------------------------------------------
1 | {
2 | "modelVersion": "5.0.0",
3 | "dependencies": {
4 | }
5 | }
--------------------------------------------------------------------------------
/hvigorfile.ts:
--------------------------------------------------------------------------------
1 | // Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
2 | export { appTasks } from '@ohos/hvigor-ohos-plugin';
--------------------------------------------------------------------------------
/oh-package-lock.json5:
--------------------------------------------------------------------------------
1 | {
2 | "lockfileVersion": 1,
3 | "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
4 | "specifiers": {
5 | "@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6",
6 | "@ohos/pulltorefresh@^2.0.1": "@ohos/pulltorefresh@2.0.1"
7 | },
8 | "packages": {
9 | "@ohos/hypium@1.0.6": {
10 | "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
11 | "integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ=="
12 | },
13 | "@ohos/pulltorefresh@2.0.1": {
14 | "resolved": "https://repo.harmonyos.com/ohpm/@ohos/pulltorefresh/-/pulltorefresh-2.0.1.har",
15 | "integrity": "sha512-DlbqTMgMvSPqZTpRFM19w081z+BV/ZPGlctfwwSNtbm3ZolM883Nmon3n/O+AGtkPagbcyPNedwqS8CBI4wNPg=="
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "modelVersion": "5.0.0",
3 | "name": "wanandroidhm",
4 | "version": "1.0.0",
5 | "description": "Please describe the basic information.",
6 | "main": "",
7 | "author": "",
8 | "license": "",
9 | "dependencies": {
10 | "@ohos/pulltorefresh": "^2.0.1"
11 | },
12 | "devDependencies": {
13 | "@ohos/hypium": "1.0.6"
14 | },
15 | "dynamicDependencies": {}
16 | }
--------------------------------------------------------------------------------
/video/wanandroidhm.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PGzxc/WanAndroidHM/42f43eab4d5bf79b0b3218906a3c77f498d0cb11/video/wanandroidhm.mp4
--------------------------------------------------------------------------------