├── .gitignore
├── AppScope
├── app.json5
└── resources
│ └── base
│ ├── element
│ └── string.json
│ └── media
│ └── app_icon.png
├── LICENSE
├── README.md
├── build-profile.json5
├── demon
├── Snipaste_2024-01-28_00-01-37.png
├── Snipaste_2024-01-28_00-01-45.png
├── Snipaste_2024-01-28_00-01-52.png
├── Snipaste_2024-01-28_00-02-05.png
└── demo.mp4
├── entry
├── .gitignore
├── build-profile.json5
├── hvigorfile.ts
├── oh-package.json5
├── patch.json
└── src
│ ├── main
│ ├── ets
│ │ ├── component
│ │ │ ├── Loading.ets
│ │ │ ├── NoData.ets
│ │ │ ├── ShowToast.ets
│ │ │ ├── ToLoad.ets
│ │ │ └── TopNav.ets
│ │ ├── entryability
│ │ │ └── EntryAbility.ts
│ │ ├── interface
│ │ │ └── index.ts
│ │ ├── pages
│ │ │ ├── AboutUs.ets
│ │ │ ├── Index.ets
│ │ │ ├── MineCollect.ets
│ │ │ ├── MineWall.ets
│ │ │ ├── SetWallpaper.ets
│ │ │ ├── Sign.ets
│ │ │ ├── UserInfo.ets
│ │ │ ├── Wallpaper.ets
│ │ │ └── navbar
│ │ │ │ ├── home_bar.ets
│ │ │ │ ├── mine_bar.ets
│ │ │ │ └── sort_bar.ets
│ │ └── utils
│ │ │ ├── data_source.ets
│ │ │ ├── env.ts
│ │ │ ├── http.ets
│ │ │ ├── storage.ets
│ │ │ └── tools.ets
│ ├── module.json5
│ └── resources
│ │ ├── base
│ │ ├── element
│ │ │ ├── color.json
│ │ │ └── string.json
│ │ ├── media
│ │ │ ├── 0.svg
│ │ │ ├── 0_.svg
│ │ │ ├── 1.svg
│ │ │ ├── 1_.svg
│ │ │ ├── 2.svg
│ │ │ ├── 2_.svg
│ │ │ ├── about.svg
│ │ │ ├── arrow.svg
│ │ │ ├── back.svg
│ │ │ ├── close.svg
│ │ │ ├── delete.svg
│ │ │ ├── icon.png
│ │ │ ├── ip_show.png
│ │ │ ├── loading.gif
│ │ │ ├── love.svg
│ │ │ ├── love_red.svg
│ │ │ ├── love_white.svg
│ │ │ ├── man.svg
│ │ │ ├── nodata.svg
│ │ │ ├── order.svg
│ │ │ ├── user.svg
│ │ │ └── woman.svg
│ │ └── 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
└── hvigor-wrapper.js
├── hvigorfile.ts
├── hvigorw
├── hvigorw.bat
├── oh-package-lock.json5
└── oh-package.json5
/.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
12 | env.ts
--------------------------------------------------------------------------------
/AppScope/app.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "bundleName": "com.wallpaper.wallpaper_app",
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": "wallpaper_app"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/AppScope/resources/base/media/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/AppScope/resources/base/media/app_icon.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 壁纸小屋
2 | - 开发中...
3 | - 接口数据来自 [wallpaper-server](https://github.com/dlongs49/wallpaper-server)库【nestjs squlize mysql】
4 | - 壁纸管理 [wallpaper-server/client](https://github.com/dlongs49/wallpaper-server/tree/main/client) 【svlete】
5 | ### 静态图演示
6 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "signingConfigs": [
4 | {
5 | "name": "default",
6 | "type": "HarmonyOS",
7 | "material": {
8 | "storePassword": "0000001CC5CBF2C327D46985A2ABEED17091F9FA4AEB4B2B44137E4A05CDB42D7B44167E9B2C267BAC348D08",
9 | "certpath": "C:/Users/dillonl/Downloads/wp.cer",
10 | "keyAlias": "wp",
11 | "keyPassword": "0000001C172ADBE333BD316A5E236EDD97A246B53AB3D0DA488AD02F941FB75BEFCCFAAB932A055CE7161F88",
12 | "profile": "C:/Users/dillonl/Downloads/wpDebug.p7b",
13 | "signAlg": "SHA256withECDSA",
14 | "storeFile": "C:/Users/dillonl/Downloads/wp.p12"
15 | }
16 | }
17 | ],
18 | "compileSdkVersion": 9,
19 | "compatibleSdkVersion": 9,
20 | "products": [
21 | {
22 | "name": "default",
23 | "signingConfig": "default",
24 | }
25 | ]
26 | },
27 | "modules": [
28 | {
29 | "name": "entry",
30 | "srcPath": "./entry",
31 | "targets": [
32 | {
33 | "name": "default",
34 | "applyToProducts": [
35 | "default"
36 | ]
37 | }
38 | ]
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/demon/Snipaste_2024-01-28_00-01-37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/demon/Snipaste_2024-01-28_00-01-37.png
--------------------------------------------------------------------------------
/demon/Snipaste_2024-01-28_00-01-45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/demon/Snipaste_2024-01-28_00-01-45.png
--------------------------------------------------------------------------------
/demon/Snipaste_2024-01-28_00-01-52.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/demon/Snipaste_2024-01-28_00-01-52.png
--------------------------------------------------------------------------------
/demon/Snipaste_2024-01-28_00-02-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/demon/Snipaste_2024-01-28_00-02-05.png
--------------------------------------------------------------------------------
/demon/demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/demon/demo.mp4
--------------------------------------------------------------------------------
/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 | "sourceOption": {
5 | "workers": [
6 | ]
7 | }
8 | },
9 | "targets": [
10 | {
11 | "name": "default",
12 | "runtimeOS": "HarmonyOS"
13 | },
14 | {
15 | "name": "ohosTest",
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/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 | "license": "",
3 | "devDependencies": {},
4 | "author": "",
5 | "name": "entry",
6 | "description": "Please describe the basic information.",
7 | "main": "",
8 | "version": "1.0.0",
9 | "dependencies": {}
10 | }
11 |
--------------------------------------------------------------------------------
/entry/patch.json:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "bundleName": "com.wallpaper.wallpaper_app",
4 | "patchVersionCode": 2000919,
5 | "versionCode": 1000000
6 | },
7 | "module": {
8 | "name": "entry",
9 | "type": "hotreload"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/entry/src/main/ets/component/Loading.ets:
--------------------------------------------------------------------------------
1 | @Preview
2 | @Component
3 | export default struct Loading {
4 |
5 | build() {
6 |
7 | Column(){
8 | Image($r("app.media.loading")).width(60).height(60)
9 | Text("加载中...").fontSize(12).margin({top:4}).fontColor(0x000000)
10 | }.position({x:"45%", y:"46%"})
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/entry/src/main/ets/component/NoData.ets:
--------------------------------------------------------------------------------
1 | import {hmRect,setBgColor} from '../utils/tools'
2 | import emitter from '@ohos.events.emitter'
3 | @Component
4 | export default struct TopNav {
5 | @Prop type: string
6 | @Prop state: number
7 | @State hmHeight: string = "100%"
8 | async aboutToAppear() {
9 | const hr = await hmRect()
10 | if(this.type == "page"){
11 | this.hmHeight = (hr.hmHeight - 300) + "px"
12 | }
13 | if(this.type == "bar"){
14 | this.hmHeight = (hr.hmHeight - 56) + "px"
15 | }
16 | }
17 | build() {
18 | Column(){
19 | Image($r("app.media.nodata")).width(140).height(140)
20 | if(this.state === 0){
21 | Text("没有找到该内容").fontColor(0x949192).fontSize(12).margin({top:10})
22 | }
23 | if(this.state === -1){
24 | Text("网络不可用").fontColor(0x949192).fontSize(12).margin({top:10})
25 | Text("点击屏幕重新加载").fontColor(0x949192).fontSize(12).margin({top:5})
26 | }
27 |
28 | }.width('100%').height(this.hmHeight).backgroundColor(0xf6f6f6).justifyContent(FlexAlign.Center).onClick(()=>{
29 | if(this.state === -1){
30 | emitter.emit({ eventId:10000 }, {data:null});
31 | }
32 | })
33 | }
34 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/component/ShowToast.ets:
--------------------------------------------------------------------------------
1 | import promptAction from '@ohos.promptAction'
2 |
3 | @Preview
4 | @Component
5 | export default struct ShowToast {
6 | build() {
7 | // 自定义待定
8 | }
9 | }
10 |
11 | export const toast = {
12 | success:(message: string, duration = 2000) => {
13 | promptAction.showToast({
14 | message,
15 | bottom: 400,
16 | duration,
17 | });
18 | },
19 | error:(message = "服务异常,请重试!",duration = 2000) => {
20 | promptAction.showToast({
21 | message,
22 | bottom: 400,
23 | duration,
24 | });
25 | }
26 | }
27 | // export const toast = Toast()
--------------------------------------------------------------------------------
/entry/src/main/ets/component/ToLoad.ets:
--------------------------------------------------------------------------------
1 | @Preview
2 | @Component
3 | export struct PullUp {
4 | // 上拉加载
5 | build() {
6 | Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
7 | Image($r("app.media.loading")).width(40).height(40)
8 | Text("加载中...").fontSize(13)
9 | }.height(50).width("100%")
10 | }
11 | }
12 |
13 |
14 | @Preview
15 | @Component
16 | export struct PullDown {
17 | @Prop hei:number
18 | @Prop pull_text:string
19 | // 下拉刷新
20 | build() {
21 | Column() {
22 | Column() {
23 | }.width(25).height(this.hei).border({ width: 1, color: 0x000000, radius: 25 }).margin({ bottom: 10 })
24 | Text(this.pull_text)
25 | .fontSize(13)
26 | .textAlign(TextAlign.Center)
27 | }.margin({ top: 10, bottom: 10 })
28 | }
29 | }
30 |
31 |
32 | @Preview
33 | @Component
34 | export struct InEnd {
35 | // 到底了
36 | build() {
37 | Text("到底了~").fontSize(13).lineHeight(50).textAlign(TextAlign.Center)
38 | }
39 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/component/TopNav.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 |
3 | @Component
4 | export default struct TopNav {
5 | @Prop title: string
6 | @Prop url: string
7 | handleTopNav: (data) => void
8 |
9 | aboutToAppear() {
10 | }
11 |
12 | build() {
13 | Row() {
14 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignContent: FlexAlign.End, alignItems: ItemAlign.End }) {
15 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
16 | Image($r("app.media.back")).width(25).height(25)
17 | }.width(50).height(50).onClick(() => {
18 | router.back({
19 | url: this.url
20 | })
21 | })
22 |
23 | Text(this.title).height(50)
24 | Flex() {
25 | }.width(40).onClick(() => {
26 | this.handleTopNav("topNav")
27 | })
28 | }.height('100%')
29 | }.width('88%').height("300px").id('topNav')
30 | }
31 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/entryability/EntryAbility.ts:
--------------------------------------------------------------------------------
1 | import UIAbility from '@ohos.app.ability.UIAbility';
2 | import window from '@ohos.window';
3 | export default class EntryAbility extends UIAbility {
4 | onCreate(want, launchParam) { }
5 | onDestroy() {}
6 | onWindowStageCreate(windowStage: window.WindowStage) {
7 | let context = this.context;
8 | let pathDir = context.filesDir;
9 | windowStage.loadContent('pages/Index', (err, data) => {
10 | if (err.code) {
11 | return;
12 | }
13 | });
14 | windowStage.getMainWindow((err, winclass) => {
15 | if(err.code){
16 | return
17 | }
18 | let av = winclass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
19 | let rect = av.topRect
20 | })
21 | }
22 |
23 | onWindowStageDestroy() {}
24 |
25 | onForeground() {}
26 |
27 | onBackground() {
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/entry/src/main/ets/interface/index.ts:
--------------------------------------------------------------------------------
1 | export interface OpearInter{
2 | icon: unknown,
3 | title: string,
4 | url: string,
5 | touchColor?:number,
6 | }
7 |
8 | export interface SignInter{
9 | uname:string,
10 | password:string
11 | }
12 | export interface SignResInter{
13 | code?:number,
14 | data?:string,
15 | msg?:string
16 | }
17 | export interface PageInter{
18 | offset?:number,
19 | limit?:number,
20 | count?:number
21 | }
22 | export interface WallItemInter{
23 | id:string,
24 | title:string,
25 | url_type:number,
26 | url:string,
27 | is_checked:boolean,
28 | color:number
29 | }
30 | export interface ParamsInter{
31 | id?:string,
32 | }
33 | export interface UinfoInter{
34 | id?:string,
35 | avatar:string,
36 | uname:string,
37 | sex?:number,
38 | sex_tit?:string,
39 | nation?:string,
40 | reg_time?:string,
41 | }
42 | export interface CollectWallInter{
43 | id:string,
44 | wallpaper_type:number,
45 | wallpaper_url:string,
46 | create_time:string,
47 | is_checked:boolean,
48 | color:number,
49 | format_date:string,
50 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/AboutUs.ets:
--------------------------------------------------------------------------------
1 | import common from '@ohos.app.ability.common';
2 | import TopNav from '../component/TopNav';
3 | import { touchBgColor } from '../utils/tools';
4 |
5 | @Entry
6 | @Component
7 | struct AboutUs {
8 | @State cardList: any = [
9 | { title: "github", url: "https://github.com/dlongs49" },
10 | { title: "gitee", url: "https://gitee.com/dlongs49" },
11 | ]
12 | @State touchBgColor: number[] = [Color.Transparent, Color.Transparent, Color.Transparent]
13 |
14 | onPageShow() {
15 | }
16 |
17 | async toUrl(url) {
18 | try {
19 | let want = {
20 | "action": "android.intent.action.VIEW",
21 | "entities": ["entity.system.browsable"],
22 | "uri": url,
23 | "type": "text/plain"
24 | }
25 | let context = getContext(this) as common.UIAbilityContext;
26 | await context.startAbility(want)
27 | console.info(`URL成功`)
28 | } catch (error) {
29 | console.info(`URI异常: ${JSON.stringify(error)}`)
30 | }
31 | }
32 |
33 | build() {
34 | Column() {
35 | TopNav({ title: "关于壁纸", url: "pages/Index" })
36 | Flex({
37 | direction: FlexDirection.Column,
38 | justifyContent: FlexAlign.Center,
39 | alignItems: ItemAlign.Center
40 | }) {
41 | Image($r("app.media.icon"))
42 | .width(70)
43 | .height(70)
44 | .borderRadius(10)
45 | .backgroundColor(0xe7e7e7)
46 | Text('壁纸小屋')
47 | .fontSize(16)
48 | .margin({ top: 14 })
49 | Text('v1.0.1')
50 | .fontSize(12)
51 | .margin({ top: 14 }).fontColor(0x8f8f8f)
52 | }.margin({ top: 50 }).height(120)
53 |
54 | List() {
55 | ForEach(this.cardList, (item: any, i: number) => {
56 | ListItem() {
57 | Flex({ justifyContent: FlexAlign.SpaceBetween }) {
58 | Text(`${item.title}`).fontSize(14).margin({ left: 14 })
59 | Image($r("app.media.arrow")).width(20).height(20)
60 | }.width("90%")
61 | }
62 | .width("100%")
63 | .height(65)
64 | .backgroundColor(this.touchBgColor[i])
65 | .onTouch((event) => {
66 | this.touchBgColor[i] = touchBgColor(event) === 0xffffff ? Color.Transparent : touchBgColor(event)
67 | })
68 | .onClick(() => {
69 | this.toUrl(item.url)
70 | })
71 | })
72 |
73 | }.width("100%").margin({ top: 40 })
74 | }.justifyContent(FlexAlign.Start).height("100%").width("100%")
75 | }
76 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/Index.ets:
--------------------------------------------------------------------------------
1 | import HomeBar from './navbar/home_bar';
2 | import SortBar from './navbar/sort_bar';
3 | import MineBar from './navbar/mine_bar';
4 | @Entry
5 | @Component
6 | struct Index {
7 | @State fontColor: string = '#182431'
8 | @State selectedFontColor: string = '#e6dd23'
9 | @State currentIndex: number = 0
10 | private controller: TabsController = new TabsController()
11 |
12 | onPageShow() {
13 | }
14 | @Builder NavigationTitle() {
15 | Column() {
16 | }.backgroundColor(this.currentIndex == 2 ? 0xe9e5fb : '').height(52).width("100%")
17 | }
18 |
19 | @Builder TabBuilder(index: number, title: string) {
20 | Column() {
21 | Image(this.currentIndex === index ? `../resources/base/media/${index}_.svg` : `../resources/base/media/${index}.svg`)
22 | .width(24)
23 | .height(24)
24 | .margin({ bottom: 4 })
25 | .objectFit(ImageFit.Contain)
26 | Text(title)
27 | .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
28 | .fontSize(10)
29 | .fontWeight(500)
30 | .lineHeight(14)
31 | }.width('100%')
32 | }
33 |
34 | build() {
35 | Navigation() {
36 | this.NavigationTitle()
37 | Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
38 | TabContent() {
39 | if (this.currentIndex == 0) {
40 | HomeBar()
41 | }
42 |
43 | }.tabBar(this.TabBuilder(0, '首页'))
44 |
45 | TabContent() {
46 | SortBar()
47 | }.tabBar(this.TabBuilder(1, '分类'))
48 |
49 | TabContent() {
50 | MineBar()
51 | }.tabBar(this.TabBuilder(2, '我的'))
52 | }
53 | .vertical(false)
54 | .barHeight(56)
55 | .onChange((index: number) => {
56 | if (index === 0) {
57 | this.selectedFontColor = '#e6dd23'
58 | } else if (index === 1) {
59 | this.selectedFontColor = '#a99ee9'
60 | } else {
61 | this.selectedFontColor = '#ea569f'
62 | }
63 | this.currentIndex = index
64 | })
65 | .width('100%')
66 | .height('94%')
67 | }.width('100%').height('100%').hideTitleBar(true)
68 | }
69 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/MineCollect.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import request from '../utils/http'
3 | import { base_url } from '../utils/env'
4 | import { CollectWallInter, PageInter } from '../interface/index'
5 | import TopNav from '../component/TopNav'
6 | import Loading from '../component/Loading'
7 | import NoData from '../component/NoData'
8 | import {PullUp,PullDown,InEnd} from '../component/ToLoad'
9 | import { toast } from '../component/ShowToast'
10 | import { connectNet, hmRect, setBgColor } from '../utils/tools'
11 | import emitter from '@ohos.events.emitter'
12 | import observer from '@ohos.telephony.observer';
13 | import connection from '@ohos.net.connection';
14 |
15 | @Entry
16 | @Component
17 | struct MineCollect {
18 | @State list: Array = []
19 | scroller: Scroller = new Scroller()
20 | @State page: PageInter = { offset: 1, limit: 12, count: -1 }
21 | @State show: boolean = false
22 | @State y: number = 80
23 | @State hmHeight: number = 0;
24 | @State loading: boolean = false
25 | @State isLoad: boolean = false // 触底分页加载状态
26 | @State isPull: boolean = false // 下拉刷新状态
27 | @State isEnd: boolean = false // 到底了没数据了状态
28 | @State hei: number = 25
29 | @State pull_text: string = "松开刷新"
30 | @State state:number = 0
31 | async aboutToAppear() {
32 | const hr = await hmRect()
33 | this.hmHeight = hr.hmHeight
34 | }
35 |
36 | onPageShow() {
37 | this.watchConnect()
38 | let innerEvent = { eventId: 10000 }
39 | emitter.on(innerEvent, this.onEventHandel.bind(this))
40 | }
41 | async watchConnect() {
42 | this.loading = true
43 | // 监听网络连接状态 模拟器无效 真机正常
44 | const state = await connectNet()
45 | this.state = state
46 | if (state === -1) {
47 | this.loading = false
48 | }
49 | if (state != -1) {
50 | this.getWallpaper(true)
51 | }
52 | }
53 | // 重新加载数据事件
54 | onEventHandel() {
55 | this.watchConnect()
56 | }
57 | // 我的收藏壁纸
58 | async getWallpaper(flag = false) {
59 | try {
60 | // 第一次进入页面的 loading 加载
61 | if (flag) {
62 | this.loading = true
63 | }
64 | let api = `/api/sign/app/get_collect_wallpaper?offset=${this.page.offset}&limit=${this.page.limit}`
65 | const res: any = await request.get(api)
66 | this.loading = this.isLoad = false
67 | if (res.code === 200) {
68 | this.page.count = res.data.count
69 | const rows = setBgColor(res.data.rows)
70 | // 此处为下拉刷新
71 | if (this.isPull || flag) {
72 | this.list = []
73 | setTimeout(()=>{
74 | this.list = rows
75 | },100)
76 | this.isPull = false
77 | this.pull_text = "松开刷新"
78 | return
79 | }
80 | this.list = [...this.list, ...rows]
81 | } else {
82 | this.isPull = false
83 | toast.error(res.msg)
84 | }
85 | } catch (err) {
86 | this.loading = this.isLoad = this.isPull = false
87 | toast.error()
88 | }
89 | }
90 | // 删除收藏的壁纸项
91 | async handleDelete() {
92 | try {
93 | const ids = this.list.filter(x => x.is_checked).map(x => x.id)
94 | if (ids.length === 0) {
95 | return
96 | }
97 | this.loading = true
98 | const res: any = await request.post("/api/sign/app/del_collect_wallpaper", ids)
99 | this.loading = false
100 | if (res.code === 200) {
101 | this.show = false
102 | this.y = 0
103 | this.page.offset = 1
104 | this.getWallpaper(true)
105 | } else {
106 | toast.error(res.msg)
107 | }
108 | } catch (err) {
109 | this.loading = false
110 | toast.error()
111 | }
112 | }
113 | build() {
114 | Column() {
115 | TopNav({ title: "我的收藏", url: "pages/Index" })
116 | if (this.page.count === 0 || this.state === -1) {
117 | NoData({ type: "bar", state: this.state })
118 | }
119 | if (this.isPull) {
120 | PullDown({hei:this.hei,pull_text:this.pull_text})
121 | }
122 | Scroll(this.scroller) {
123 | Column() {
124 | Grid() {
125 | ForEach(this.list, (item: CollectWallInter, idx: number) => {
126 | GridItem() {
127 | Column() {
128 | Stack() {
129 | Column() {
130 | Image(item.wallpaper_type == 0 ? base_url + item.wallpaper_url : item.wallpaper_url)
131 | .width("100%")
132 | .height(200)
133 | .borderRadius(10)
134 | .backgroundColor(item.color)
135 | Text(item.format_date).fontSize(10).margin({ top: 5, right: 5 }).fontColor(0x585858)
136 | }.alignItems(HorizontalAlign.End)
137 |
138 | if (this.show) {
139 | Checkbox({ name: item.id, group: 'checkIds', })
140 | .select(item.is_checked)
141 | .selectedColor(0x027eff)
142 | .position({ x: '74%', y: 170 })
143 | .onChange((value: boolean) => {
144 | // 选中当前项更改选中状态
145 | this.list[idx].is_checked = value
146 | let flag = this.list.find(x => x.is_checked)
147 | if (!flag) {
148 | this.y = 80
149 | this.show = false
150 | }
151 | })
152 | }
153 | }.gesture(
154 | LongPressGesture({ repeat: true, duration: 200 })
155 | .onAction((event: GestureEvent) => {
156 | if (event.repeat) {
157 | // 长按选中当前这一项 使其删除控件出现 更改 y 执行动画
158 | this.list[idx].is_checked = true
159 | this.show = true
160 | this.y = 0
161 | }
162 | })
163 | .onActionEnd(() => {
164 | })
165 | )
166 | }.width("100%").alignItems(HorizontalAlign.End).onClick((e: ClickEvent) => {
167 | router.pushUrl({
168 | url: "pages/SetWallpaper",
169 | params: {
170 | id: item.id
171 | }
172 | })
173 | })
174 | }.width("30%").margin({ bottom: 18 })
175 | }, item => item)
176 | }
177 | .columnsTemplate("lfr lfr lfr")
178 | .columnsGap(12)
179 | .rowsGap(10)
180 | .layoutDirection(GridDirection.Row)
181 | .width("90%")
182 |
183 | if (this.isLoad) {
184 | PullUp()
185 | }
186 | if (this.isEnd) {
187 | InEnd()
188 | }
189 | }.constraintSize({minHeight:this.hmHeight+ 'px'})
190 | }
191 | .height(!this.show ? this.hmHeight - 300 + 'px' : (this.hmHeight - 570) + 'px')
192 | .width("100%")
193 | .edgeEffect(EdgeEffect.Spring)
194 | .onScroll(() => {
195 | let y = this.scroller.currentOffset().yOffset
196 | // y 为 负数则为下拉刷新 为正为上拉加载 || 正在删除选中状态,不执行分页加载
197 | if (y > 0 || this.show) {
198 | return
199 | }
200 | this.pull_text = "松开刷新"
201 | const scroll_y = Math.floor(Math.abs(y))
202 | if (scroll_y === 0) {
203 | this.pull_text = "刷新中"
204 | }
205 | // 保持加载的圆形有高度
206 | if (scroll_y > 24) {
207 | this.isPull = true
208 | this.hei = scroll_y
209 | }
210 | })
211 | .onScrollStop(() => {
212 | // 正在删除选中状态,不执行分页加载
213 | if(this.show){
214 | return
215 | }
216 | // 滚动条停止滚动 判断是刷新操作,避免上拉加载执行
217 | if (this.isPull) {
218 | this.pull_text = "刷新中"
219 | this.page.offset = 1
220 | this.getWallpaper()
221 | }
222 | })
223 | .onScrollEdge((side: Edge) => {
224 | // 正在删除选中状态,不执行分页加载
225 | if(this.show){
226 | return
227 | }
228 | // 上拉分页加载
229 | if (Edge.Bottom === side) {
230 | // 分页加载的长度等于总数则不往下执行
231 | if (this.list.length === this.page.count) {
232 | this.isLoad = false
233 | this.isEnd = true
234 | return
235 | }
236 | // 如果当前上拉分页loading状态还未完成,不让其往下 执行
237 | if (this.isLoad) {
238 | return
239 | }
240 | // 分页加一 执行分页加载
241 | this.isLoad = true
242 | this.page.offset++
243 | this.getWallpaper()
244 | }
245 | })
246 | Flex({ justifyContent: FlexAlign.Center }) {
247 | Column() {
248 | Image($r('app.media.delete')).width(20).height(20)
249 | Text("删除").fontSize(12).margin({ top: 5 })
250 | }
251 | .width("100%")
252 | .width(40)
253 | .margin({ top: 15 })
254 | .onClick(() => {
255 | this.handleDelete()
256 |
257 | })
258 | }.backgroundColor(0xf5f5f5).height("270px").translate({ y: this.y }).animation({
259 | duration: 200,
260 | })
261 |
262 | if (this.loading) {
263 | Loading()
264 | }
265 | }.width('100%')
266 | }
267 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/MineWall.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import prompt from '@ohos.prompt'
3 | import fs from '@ohos.file.fs';
4 | import request from '../utils/http'
5 | import { base_url } from '../utils/env'
6 | import { OpearInter, PageInter, UinfoInter, WallItemInter } from '../interface/index'
7 | import TopNav from '../component/TopNav'
8 | import wallpaper from '@ohos.wallpaper';
9 | import { toast } from '../component/ShowToast';
10 |
11 | @Entry
12 | @Component
13 | struct MineWall {
14 | @State fontColor: string = '#182431'
15 | @State selectedFontColor: string = '#e6dd23'
16 | @State currentIndex: number = 0
17 | @State list: Array = []
18 | scroller: Scroller = new Scroller()
19 | home_scroller: Scroller = new Scroller()
20 | @State page: PageInter = { offset: 1, limit: 20, count: 0 }
21 |
22 | onPageShow() {
23 | this.getMineWallpaper()
24 | let filenames = fs.listFileSync(getContext(this).filesDir, {
25 | "filter": {
26 | "suffix": [".png", ".jpg", ".jpeg"]
27 | }
28 | });
29 | console.log("********",JSON.stringify(filenames))
30 | }
31 | // 我的壁纸
32 | async getMineWallpaper() {
33 | try {
34 | let api = `/wapi/api/sign/app/get_apply_wallpaper?offset=${this.page.offset}&limit=${this.page.limit}`
35 | const res: any = await request.post(api)
36 | if (res.code === 200) {
37 | this.page.count = res.data.count
38 | this.list = res.data.rows
39 | } else {
40 | toast.error(res.msg);
41 | }
42 | } catch (err) {
43 | toast.error();
44 | }
45 | }
46 |
47 | build() {
48 | Column() {
49 | TopNav({ title: "我的壁纸", url: "pages/Index" })
50 | Scroll(this.scroller) {
51 | Grid() {
52 | ForEach(this.list, (item: WallItemInter, idx: number) => {
53 | GridItem() {
54 | Stack() {
55 | Image(item.url_type == 0 ? base_url + item.url : item.url)
56 | .width("100%")
57 | .height(200)
58 | .borderRadius(10)
59 | .backgroundColor(0xffdbdbdb)
60 |
61 | Row() {
62 | Text("锁屏 桌面").fontSize(10).fontColor(0xffffff)
63 | }
64 | .position({ y: 170, x: 10 })
65 | .backgroundColor(0x60000000)
66 | .opacity(0.9)
67 | .borderRadius(8)
68 | .padding({ left: 7, right: 7, top: 3, bottom: 3 })
69 | }.width("100%").onClick((e: ClickEvent) => {
70 | router.pushUrl({
71 | url: "pages/SetWallpaper",
72 | params: {
73 | id: item.id
74 | }
75 | })
76 | })
77 | }.width("33%").margin({ bottom: 18 })
78 | }, item => item)
79 | }
80 | .width('90%')
81 | .height('100%')
82 | .columnsTemplate("1fr 1fr 1fr")
83 | .columnsGap(12)
84 | }
85 | }.width('100%')
86 | }
87 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/SetWallpaper.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import use_request from '@ohos.request';
3 | import request from '../utils/http'
4 | import { ParamsInter } from '../interface/index'
5 | import { base_url } from '../utils/env'
6 | import { getRandomColor } from "../utils/tools"
7 | import { toast } from '../component/ShowToast'
8 | import Loading from '../component/Loading'
9 | import wallpaper from '@ohos.wallpaper';
10 |
11 |
12 | @CustomDialog
13 | struct CustomDialogComm {
14 | controller: CustomDialogController
15 | @Link currentItem: any
16 |
17 | // 设置壁纸
18 | setWallpaperApplication(type) {
19 | let downloadTask
20 | try {
21 | let file_name = this.currentItem.url.slice(this.currentItem.url.lastIndexOf('/'), this.currentItem.url.length)
22 | let filePath = getContext(this).filesDir + file_name
23 | use_request.downloadFile(getContext(this), {
24 | url: this.currentItem.url_type == 0 ? base_url + this.currentItem.url : this.currentItem.url,
25 | filePath,
26 | }, (err, data) => {
27 | if (err) {
28 | console.log("错误:", JSON.stringify(err))
29 | return
30 | }
31 | downloadTask = data
32 | let progresCallback = (receivedSize, totalSize) => {
33 | console.info("下载壁纸进度:" + receivedSize + " totalSize:" + totalSize);
34 | };
35 | downloadTask.on('progress', progresCallback);
36 | let failCallback = (err) => {
37 | console.info('下载壁纸失败:', JSON.stringify(err));
38 |
39 | };
40 | downloadTask.on('fail', failCallback);
41 | let completeCallback = () => {
42 | if (type === 0) {
43 | wallpaper.setWallpaper(filePath, wallpaper.WallpaperType.WALLPAPER_SYSTEM, (error) => {
44 | if (error) {
45 | console.error(`设置主屏壁纸错误: ${JSON.stringify(error)}`);
46 | return;
47 | }
48 | console.log("设置主屏壁纸成功");
49 | });
50 | }
51 | if (type === 1) {
52 | wallpaper.setWallpaper(filePath, wallpaper.WallpaperType.WALLPAPER_LOCKSCREEN, (error) => {
53 | if (error) {
54 | console.error(`设置锁屏壁纸错误: ${JSON.stringify(error)}`);
55 | return;
56 | }
57 | console.log("设置锁屏壁纸成功");
58 | });
59 | }
60 | if (type === 2) {
61 | wallpaper.setWallpaper(filePath, wallpaper.WallpaperType.WALLPAPER_SYSTEM, (error) => {
62 | if (error) {
63 | console.error(`设置主屏壁纸错误: ${JSON.stringify(error)}`);
64 | return;
65 | }
66 | console.log("设置主屏壁纸成功");
67 | });
68 | wallpaper.setWallpaper(filePath, wallpaper.WallpaperType.WALLPAPER_LOCKSCREEN, (error) => {
69 | if (error) {
70 | console.error(`设置锁屏壁纸错误: ${JSON.stringify(error)}`);
71 | return;
72 | }
73 | console.log("设置锁屏壁纸成功");
74 | });
75 | }
76 | };
77 | downloadTask.on('complete', completeCallback);
78 | let pauseCallback = () => {
79 | console.info('下载壁纸暂停');
80 | };
81 | downloadTask.on('pause', pauseCallback);
82 | downloadTask.getTaskInfo((err, downloadInfo) => {
83 | if (err) {
84 | console.error('下载信息[error]:', JSON.stringify(err));
85 | } else {
86 | console.info('下载信息[info]:', JSON.stringify(downloadInfo));
87 | }
88 | });
89 | })
90 |
91 | } catch (err) {
92 | console.error("downloadTask异常:", JSON.stringify(err));
93 | }
94 | }
95 | build() {
96 | Column() {
97 | Button({ type: ButtonType.Normal }) {
98 | Text("应用锁屏").fontColor(0x000000).width("90%")
99 | }.width("100%").height(50).backgroundColor(0xffffff).onClick(() => {
100 | this.setWallpaperApplication(1)
101 | })
102 |
103 | Button({ type: ButtonType.Normal }) {
104 | Text("应用桌面").fontColor(0x000000).width("90%")
105 | }.width("100%").height(50).backgroundColor(0xffffff).onClick(() => {
106 | this.setWallpaperApplication(0)
107 | })
108 |
109 | Button({ type: ButtonType.Normal }) {
110 | Text("应用全部").fontColor(0x000000).width("90%")
111 | }.width("100%").height(50).backgroundColor(0xffffff).onClick(() => {
112 | this.setWallpaperApplication(2)
113 | })
114 |
115 | Button('取消', { type: ButtonType.Capsule, stateEffect: true })
116 | .backgroundColor(0xeeeeee)
117 | .width("90%")
118 | .height(44)
119 | .margin({ top: 15 })
120 | .fontColor(0x000000)
121 | .onClick(() => {
122 | this.controller.close()
123 | })
124 | }.backgroundColor(0xffffff).borderRadius(14).padding({ top: 25, bottom: 20 }).width("90%")
125 | }
126 | }
127 |
128 | @Entry
129 | @Component
130 | struct SetWallpaper {
131 | @State currentItem: any = { is_like: 0 }
132 | @State loading: boolean = false
133 |
134 | aboutToAppear() {
135 | let params: ParamsInter = router.getParams();
136 | this.getWallpaperDetail(params.id)
137 | }
138 | // 当前壁纸
139 | async getWallpaperDetail(id: string) {
140 | try {
141 | this.loading = true
142 | let api = `/api/wallpaper/app/detail_wallpaper/${id}`
143 | const res: any = await request.get(api)
144 | if (res.code === 200) {
145 | this.currentItem = res.data
146 | } else {
147 | toast.error(res.msg)
148 | }
149 | } catch (err) {
150 | toast.error()
151 | }
152 | }
153 | // 收藏
154 | async handleCollect() {
155 | try {
156 | const res: any = await request.post(`/api/sign/app/collect_wallpaper?wallpaper_id=${this.currentItem.id}`)
157 | if (res.code === 200) {
158 | this.currentItem.is_like = this.currentItem.is_like == 0 ? 1 : 0
159 | toast.error(res.msg)
160 | }
161 |
162 | } catch (err) {
163 | toast.error()
164 | }
165 | }
166 |
167 | dialogController: CustomDialogController = new CustomDialogController({
168 | builder: CustomDialogComm({
169 | currentItem:$currentItem
170 | }),
171 | alignment: DialogAlignment.Bottom,
172 | offset: { dx: 0, dy: -20 },
173 | autoCancel: true,
174 | customStyle: true
175 | })
176 |
177 | build() {
178 | Stack({ alignContent: Alignment.TopStart }) {
179 | Image(this.currentItem.url_type == 0 ? base_url + this.currentItem.url : this.currentItem.url)
180 | .width("100%")
181 | .height("100%")
182 | .backgroundColor(getRandomColor())
183 | .onComplete(() => {
184 | this.loading = false
185 | })
186 |
187 | Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
188 | Image($r("app.media.close")).width("70px").height("70px")
189 | }
190 | .position({ x: "82%", y: '6%' })
191 | .width("120px")
192 | .height("120px")
193 | .backgroundColor(0x000000)
194 | .opacity(0.4)
195 | .borderRadius(100)
196 | .onClick(() => {
197 | router.back({ url: 'pages/Index' });
198 | })
199 |
200 | Row() {
201 | Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
202 | Image(this.currentItem.is_like === 0 ? $r("app.media.love_white") : $r("app.media.love_red"))
203 | .width(20)
204 | .height(20)
205 | .margin({ right: 20 })
206 | }.width(40).height(40).onClick(() => {
207 | this.handleCollect()
208 | })
209 |
210 | Button('应用壁纸', { type: ButtonType.Capsule, stateEffect: true })
211 | .backgroundColor(0xffffff)
212 | .width("80%")
213 | .fontColor(0x000000)
214 | .onClick(() => {
215 | if (this.dialogController != undefined) {
216 | this.dialogController.open()
217 | }
218 | })
219 | }.position({ y: "92%", x: '5%' }).width("90%")
220 |
221 | if (this.loading) {
222 | Loading()
223 | }
224 | }.height("100%").width("100%")
225 | }
226 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/Sign.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import { SignInter } from '../interface/index'
3 | import request from '../utils/http'
4 | import storage from '../utils/storage'
5 | import { toast } from '../component/ShowToast'
6 |
7 | @Entry
8 | @Component
9 | struct Sign {
10 | controller: TextInputController = new TextInputController()
11 | @State form: SignInter = {
12 | uname: "wallpaper",
13 | password: "string"
14 | }
15 | @State loading: boolean = false
16 |
17 | onPageShow() {
18 | }
19 |
20 | async sign_in() {
21 | try {
22 | this.loading = true
23 | const res: any = await request.post("/api/sign/reg_login", this.form)
24 | this.loading = false
25 | if (res.code === 200) {
26 | await storage.set('token', res.data)
27 | router.replaceUrl({
28 | url: "pages/Index"
29 | })
30 | } else {
31 | toast.error(res.msg)
32 | }
33 | } catch (err) {
34 | this.loading = false
35 | toast.error()
36 | }
37 | }
38 |
39 | @Builder NavigationTitle() {
40 | Column() {
41 | }.backgroundColor(0xe9e5fb).height(52).width("100%")
42 | }
43 |
44 | build() {
45 | Navigation() {
46 | this.NavigationTitle()
47 | Column() {
48 |
49 | Column() {
50 | Image($r("app.media.icon")).width(60).height(60).borderRadius(10)
51 | }
52 | .height(200)
53 | .width("100%")
54 | .margin({ left: 10, right: 10, bottom: 70 })
55 | .backgroundColor(0xffffff)
56 | .borderRadius({
57 | bottomLeft: 60,
58 | bottomRight: 60
59 | })
60 | .justifyContent(FlexAlign.Center)
61 | Column() {
62 | TextInput({ text: this.form.uname, placeholder: '请输入账号', controller: this.controller })
63 | .placeholderFont({ size: 14, weight: 400 })
64 | .caretColor(0xa794ff)
65 | .width('100%')
66 | .height('100%')
67 | .fontSize(14)
68 | .fontColor(0x000000)
69 | .fontWeight(500)
70 | .backgroundColor(0xffffff)
71 | .stateStyles({
72 | pressed: {
73 | .backgroundColor(Color.Transparent)
74 | }
75 | })
76 | .onChange((value: string) => {
77 | this.form.uname = value
78 | })
79 | }
80 | .width("90%")
81 | .height(48)
82 | .backgroundColor(0xffffff)
83 | .borderRadius(12)
84 | .borderWidth(2)
85 | .borderColor(0xa794ff)
86 |
87 | Column() {
88 | TextInput({ text: this.form.password, placeholder: '请输入密码', controller: this.controller })
89 | .placeholderFont({ size: 14, weight: 400 })
90 | .caretColor(0xa794ff)
91 | .type(InputType.Password)
92 | .showPasswordIcon(false)
93 | .width('100%')
94 | .height('100%')
95 | .fontSize(14)
96 | .fontColor(0x000000)
97 | .fontWeight(500)
98 | .backgroundColor(0xffffff)
99 | .stateStyles({
100 | pressed: {
101 | .backgroundColor(Color.Transparent)
102 | }
103 | })
104 | .onChange((value: string) => {
105 | this.form.password = value
106 | })
107 | }
108 | .width("90%")
109 | .height(48)
110 | .backgroundColor(0xffffff)
111 | .borderRadius(12)
112 | .borderWidth(2)
113 | .margin({ top: 20 })
114 | .borderColor(0xa794ff)
115 |
116 | Button({ type: ButtonType.Capsule, stateEffect: true }) {
117 | Row() {
118 | if (this.loading) {
119 | LoadingProgress().width(24).height(24).margin({ left: 12 }).color(0xFFFFFF)
120 | }
121 | Text('登录/注册').fontSize(16).fontColor(0xffffff).margin({ left: 5 })
122 | }.alignItems(VerticalAlign.Center).height(46)
123 | }
124 | .backgroundColor(0xa794ff)
125 | .width("90%")
126 | .margin({ top: 40 })
127 |
128 | Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
129 | Image($r("app.media.back")).width("70px").height("70px")
130 | }
131 | .position({ x: "4%", y: '2%' })
132 | .width("120px")
133 | .height("120px")
134 | .onClick(() => {
135 | router.back({ url: 'pages/Index' });
136 | })
137 | }
138 | .justifyContent(FlexAlign.Start)
139 | .height("100%")
140 | .width("100%")
141 | .linearGradient({
142 | direction: GradientDirection.Top,
143 | angle: 180,
144 | colors: [[0xe9e5fb, 0.0], [0xffffff, 0.5], [0xffffff, 1.0]]
145 | })
146 | .onClick(() => {
147 | this.sign_in()
148 | })
149 | }.width('100%').height('100%').hideTitleBar(true)
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/UserInfo.ets:
--------------------------------------------------------------------------------
1 | import picker from '@ohos.file.picker';
2 | import uploadRequest from '@ohos.request';
3 | import fs from '@ohos.file.fs';
4 | import { SignInter, UinfoInter } from '../interface/index'
5 | import request from '../utils/http'
6 | import storage from '../utils/storage'
7 | import TopNav from '../component/TopNav'
8 | import Loading from '../component/Loading'
9 | import { toast } from '../component/ShowToast'
10 | import { touchBgColor } from '../utils/tools'
11 | import { base_url } from '../utils/env';
12 |
13 |
14 | @CustomDialog
15 | struct DialogEditUname {
16 | @Link uname: string
17 | inputController: TextInputController = new TextInputController()
18 | controller: CustomDialogController
19 | onCancel: () => void
20 | onSubmit: () => void
21 |
22 | build() {
23 | Column() {
24 | Text("编辑昵称").fontSize(18)
25 | Column() {
26 | TextInput({ text: this.uname, controller: this.inputController })
27 | .placeholderFont({ size: 14, weight: 400 })
28 | .caretColor(0xa794ff)
29 | .showPasswordIcon(false)
30 | .width('100%')
31 | .height('100%')
32 | .fontSize(14)
33 | .fontColor(0x000000)
34 | .fontWeight(500)
35 | .backgroundColor(0xffffff)
36 | .stateStyles({
37 | pressed: {
38 | .backgroundColor(Color.Transparent)
39 | }
40 | })
41 | .onChange((value: any) => {
42 | this.uname = value;
43 | })
44 | }
45 | .width("90%")
46 | .height(48)
47 | .backgroundColor(0xffffff)
48 | .borderRadius(12)
49 | .borderWidth(2)
50 | .margin({ top: 20, bottom: 20 })
51 | .borderColor(0xa794ff)
52 |
53 | Flex({ justifyContent: FlexAlign.Center }) {
54 | Button('取消', { type: ButtonType.Capsule, stateEffect: true })
55 | .backgroundColor(0xeeeeee)
56 | .width("40%")
57 | .height(44)
58 | .fontColor(0x000000)
59 | .onClick(() => {
60 | this.controller.close()
61 | })
62 | Button('确定', { type: ButtonType.Capsule, stateEffect: true })
63 | .backgroundColor(0xa794ff)
64 | .width("40%")
65 | .height(44)
66 | .margin({ left: 15 })
67 | .fontColor(0xffffff)
68 | .onClick(async () => {
69 | try {
70 | const res: any = await request.post("/api/sign/put_user", { uname: this.uname })
71 | if (res.code === 200) {
72 | } else {
73 | toast.error(res.msg)
74 | }
75 | } catch (err) {
76 | toast.error()
77 | }
78 | this.onSubmit()
79 |
80 | })
81 | }.margin({ top: 10 })
82 |
83 | }.backgroundColor(0xffffff).borderRadius(14).padding({ top: 25, bottom: 20 }).width("90%")
84 | }
85 | }
86 |
87 |
88 | @Entry
89 | @Component
90 | struct UserInfo {
91 | controller: TextInputController = new TextInputController()
92 | @State uname: string = ""
93 | @State sex_tit: string = "男"
94 | @State sex: string = "1"
95 | @State touchBgColor_1: number = 0xffffff
96 | @State touchBgColor_2: number = 0xffffff
97 | @State touchBgColor_3: number = 0xffffff
98 | @State touchBgColor_4: number = 0xffffff
99 | @State touchBgColor_5: number = 0xffffff
100 | @State loading: boolean = false
101 | @State info: UinfoInter = {
102 | avatar: "",
103 | sex_tit: "",
104 | uname: ""
105 | }
106 |
107 | onPageShow() {
108 | this.getUserInfo()
109 | }
110 |
111 | onCancel() {
112 | this.dialogController.close()
113 | }
114 |
115 | onSubmit() {
116 | this.dialogController.close()
117 | this.info.uname = this.uname
118 | }
119 | // 打开相册
120 | async selectImage() {
121 | try {
122 | let PhotoSelectOptions = new picker.PhotoSelectOptions();
123 | PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
124 | PhotoSelectOptions.maxSelectNumber = 1
125 | const photoPicker = new picker.PhotoViewPicker();
126 | const result = await photoPicker.select(PhotoSelectOptions)
127 | this.uploadAvatar(result)
128 | console.log("选择的图片文件:", JSON.stringify(result))
129 | } catch (e) {
130 | console.log("打开相册错误:", JSON.stringify(e))
131 | }
132 | }
133 | // 上传头像
134 | async uploadAvatar(data: any) {
135 | try {
136 | const file = fs.openSync(data.photoUris[0], fs.OpenMode.READ_ONLY)
137 | const spm = new Date().getTime().toString()
138 | const dstPath = getContext(this).cacheDir + "/" + spm + '.png'
139 | fs.copyFileSync(file.fd, dstPath);
140 | let uri = "internal://cache/" + dstPath.split("cache/")[1];
141 | console.log("***********", dstPath, uri)
142 | const uploadTask = await uploadRequest.uploadFile(getContext(this), {
143 | url: base_url + '/api/upload/avatar',
144 | header: { 'Accept': '*/*' },
145 | method: "POST",
146 | files: [{ filename: `${spm}.png`, name: "avatar", uri, type: 'image/png' }],
147 | data: []
148 | })
149 | uploadTask.on("complete", (data) => {
150 | this.getAvatarPath(data[0].path)
151 | })
152 | } catch (e) {
153 | console.log("上传图片异常:", JSON.stringify(e))
154 | }
155 | }
156 | // 获取上传的头像路径
157 | async getAvatarPath(file_name) {
158 | try {
159 | const res: any = await request.get(`/api/upload/path?file_name=${file_name}`)
160 | if (res.code === 200) {
161 | this.updateUserInfo({ avatar: res.data.file_path })
162 | } else {
163 | toast.error("未找到该头像资源")
164 | }
165 | } catch (e) {
166 | toast.error()
167 | }
168 | }
169 | //个人信息
170 | async getUserInfo() {
171 | try {
172 | const res: any = await request.get("/api/sign/get_user")
173 | if (res.code === 200) {
174 | this.info = res.data
175 | let dateStr: string[] = new Date(res.data.reg_time).toLocaleDateString().split("/")
176 | this.info.reg_time = `${dateStr[2]}-${dateStr[0]}-${dateStr[1]}`
177 | } else {
178 | toast.error(res.msg)
179 | }
180 | } catch (err) {
181 | toast.error()
182 | }
183 | }
184 | // 更新用户信息
185 | async updateUserInfo(params) {
186 | try {
187 | const res: any = await request.post("/api/sign/put_user", params)
188 | if (res.code === 200) {
189 | if (params.uname) {
190 | this.info.uname = this.uname
191 | this.dialogController.close()
192 | }
193 | if (params.sex) {
194 | this.info.sex_tit = this.sex_tit
195 | }
196 | if (params.avatar) {
197 | this.info.avatar = params.avatar
198 | }
199 | } else {
200 | toast.error(res.msg)
201 | }
202 | } catch (err) {
203 | toast.error()
204 | }
205 | }
206 |
207 | dialogController: CustomDialogController = new CustomDialogController({
208 | builder: DialogEditUname({
209 | onCancel: this.onCancel,
210 | onSubmit: this.onSubmit,
211 | uname: $uname,
212 | }),
213 | alignment: DialogAlignment.Bottom,
214 | offset: { dx: 0, dy: -40 },
215 | autoCancel: true,
216 | customStyle: true
217 | })
218 |
219 | build() {
220 | Column() {
221 | TopNav({ title: "", url: "pages/Index" })
222 | Column() {
223 | Text("我的信息").fontSize(30).textAlign(TextAlign.Start).fontWeight(200).width("90%")
224 | Text("基础资料")
225 | .fontSize(10)
226 | .fontColor(0x999999)
227 | .textAlign(TextAlign.Start)
228 | .width("90%")
229 | .margin({ top: 20, bottom: 15 })
230 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
231 | Text("头像")
232 | .fontSize(16)
233 | .fontWeight(800)
234 | .margin({ left: 20 })
235 | .height("100%")
236 | .lineHeight(26)
237 | Row() {
238 | Image(this.info.avatar ? base_url + this.info.avatar : $r('app.media.user')).width(40).height(40).border({
239 | width: 1,
240 | color: 0xeeeeee,
241 | radius: 40,
242 | })
243 | Image($r("app.media.arrow")).width(20).height(25).fillColor(0xcccccc)
244 | }.height("100%").width("70%").justifyContent(FlexAlign.End).margin({ right: 25 })
245 | }.width("100%").height(60).backgroundColor(this.touchBgColor_1).onTouch((event) => {
246 | this.touchBgColor_1 = touchBgColor(event)
247 | this.selectImage()
248 | })
249 |
250 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
251 | Text("昵称")
252 | .fontSize(16)
253 | .fontWeight(800)
254 | .margin({ left: 20 })
255 | .height("100%")
256 | .lineHeight(26)
257 | Row() {
258 | Text(this.info.uname).fontSize(14).fontColor(0x999999)
259 | Image($r("app.media.arrow")).width(20).height(25).fillColor(0xcccccc)
260 | }.height("100%").width("70%").justifyContent(FlexAlign.End).margin({ right: 25 })
261 | }
262 | .width("100%")
263 | .height(60)
264 | .backgroundColor(this.touchBgColor_2)
265 | .onTouch((event) => {
266 | this.touchBgColor_2 = touchBgColor(event)
267 | })
268 | .onClick(() => {
269 | if (this.dialogController != undefined) {
270 | this.uname = this.info.uname
271 | this.dialogController.open()
272 | }
273 | })
274 |
275 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
276 | Text("注册日期")
277 | .fontSize(16)
278 | .fontWeight(800)
279 | .margin({ left: 20 })
280 | .height("100%")
281 | .lineHeight(26)
282 | Row() {
283 | Text(this.info.reg_time).fontSize(14).fontColor(0x999999)
284 | Image($r("app.media.arrow")).width(20).height(25).fillColor(0xcccccc)
285 | }.height("100%").width("70%").justifyContent(FlexAlign.End).margin({ right: 25 })
286 | }.width("100%").height(60).backgroundColor(this.touchBgColor_3).onTouch((event) => {
287 | this.touchBgColor_3 = touchBgColor(event)
288 | })
289 |
290 | Column() {
291 | }.width("90%").height(1).backgroundColor(0xf2f2f2).margin({ top: 10, bottom: 10 })
292 |
293 | Text("详细资料")
294 | .fontSize(10)
295 | .fontColor(0x999999)
296 | .textAlign(TextAlign.Start)
297 | .width("90%")
298 | .margin({ top: 20, bottom: 20 })
299 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
300 | Text("性别")
301 | .fontSize(16)
302 | .fontWeight(800)
303 | .margin({ left: 20 })
304 | .height("100%")
305 | .lineHeight(26)
306 | Row() {
307 | Select([
308 | { value: '女', icon: $r("app.media.woman") },
309 | { value: '男', icon: $r("app.media.man") },
310 | ])
311 | .value(this.info.sex_tit)
312 | .font({ size: 16, weight: 500 })
313 | .fontColor(0x999999)
314 | .optionFont({ size: 16, weight: 400 })
315 | .onSelect((index: number) => {
316 | this.sex_tit = index == 1 ? "男" : "女"
317 | this.sex = index == 1 ? "1" : "0"
318 | this.updateUserInfo({ sex: this.sex, sex_tit: this.sex_tit })
319 | })
320 | }.height("100%").width("70%").justifyContent(FlexAlign.End).margin({ right: 25 })
321 |
322 | }.width("100%").height(60).backgroundColor(this.touchBgColor_4).onTouch((event) => {
323 | this.touchBgColor_4 = touchBgColor(event)
324 | })
325 |
326 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
327 | Text("国家/地区")
328 | .fontSize(16)
329 | .fontWeight(800)
330 | .margin({ left: 20 })
331 | .height("100%")
332 | .lineHeight(26)
333 | Text(this.info.nation)
334 | .fontSize(14)
335 | .fontColor(0x999999)
336 | .height("100%")
337 | .width("70%")
338 | .textAlign(TextAlign.End)
339 | .margin({ right: 25 })
340 | }.width("100%").height(60).backgroundColor(this.touchBgColor_5).onTouch((event) => {
341 | this.touchBgColor_5 = touchBgColor(event)
342 | })
343 |
344 | }.width("100%")
345 | }
346 | .width("100%")
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/Wallpaper.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import request from '../utils/http'
3 | import { base_url } from '../utils/env'
4 | import { PageInter, ParamsInter, WallItemInter } from '../interface/index'
5 | import TopNav from '../component/TopNav'
6 | import Loading from '../component/Loading'
7 | import NoData from '../component/NoData'
8 | import {PullUp,PullDown,InEnd} from '../component/ToLoad'
9 | import { toast } from '../component/ShowToast'
10 | import { connectNet, hmRect, setBgColor } from '../utils/tools'
11 | import emitter from '@ohos.events.emitter'
12 |
13 | @Entry
14 | @Component
15 | struct Wallpaper {
16 | @State list: Array = []
17 | scroller: Scroller = new Scroller()
18 | @State page: PageInter = { offset: 1, limit: 6, count: -1 }
19 | @State loading: boolean = false
20 | @State hmHeight: string = "90%";
21 | @State type_id: string = ""
22 | @State isLoad: boolean = false // 触底分页加载状态
23 | @State isPull: boolean = false // 下拉刷新状态
24 | @State isEnd: boolean = false // 到底了没数据了状态
25 | @State hei: number = 25
26 | @State pull_text: string = "松开刷新"
27 | @State state:number = 0
28 | async aboutToAppear() {
29 | const hr = await hmRect()
30 | this.hmHeight = hr.hmHeight - 300 + 'px'
31 | }
32 |
33 | onPageShow() {
34 | let params: ParamsInter = router.getParams();
35 | this.type_id = params?.id
36 | this.watchConnect()
37 | let innerEvent = { eventId: 10000 }
38 | emitter.on(innerEvent, this.onEventHandel.bind(this))
39 | }
40 | async watchConnect() {
41 | this.loading = true
42 | // 监听网络连接状态 模拟器无效 真机正常
43 | const state = await connectNet()
44 | this.state = state
45 | if (state === -1) {
46 | this.loading = false
47 | }
48 | if (state != -1) {
49 | this.getWallpaper(true)
50 | }
51 | }
52 | // 重新加载数据事件
53 | onEventHandel() {
54 | this.watchConnect()
55 | }
56 | // 壁纸
57 | async getWallpaper(flag = false) {
58 | try {
59 | // 第一次进入页面的 loading 加载
60 | if (flag) {
61 | this.loading = true
62 | }
63 | let api = `/api/wallpaper/app/get_wallpaper?offset=${this.page.offset}&limit=${this.page.limit}`
64 | const res: any = await request.post(api, { type_id: this.type_id})
65 | this.loading = this.isLoad = false
66 | if (res.code === 200) {
67 | this.page.count = res.data.count
68 | // 给图片增加背景交互色
69 | const rows = setBgColor(res.data.rows)
70 | // 此处为下拉刷新
71 | if (this.isPull) {
72 | this.list = rows
73 | this.isPull = false
74 | this.pull_text = "松开刷新"
75 | return
76 | }
77 | this.list = [...this.list, ...rows]
78 | } else {
79 | this.isPull = false
80 | toast.error(res.msg)
81 | }
82 | } catch (err) {
83 | this.loading = this.isLoad = this.isPull = false
84 | toast.error()
85 | }
86 | }
87 |
88 | build() {
89 | Column() {
90 | TopNav({ title: "壁纸中心", url: "pages/Index" })
91 | if (this.page.count === 0 || this.state === -1) {
92 | NoData({ type: "bar", state: this.state })
93 | }
94 | if (this.isPull) {
95 | PullDown({hei:this.hei,pull_text:this.pull_text})
96 | }
97 | Scroll(this.scroller) {
98 | Column() {
99 | Grid() {
100 | ForEach(this.list, (item: WallItemInter, idx: number) => {
101 | GridItem() {
102 | Column() {
103 | Column() {
104 | Image(item.url_type == 0 ? base_url + item.url : item.url)
105 | .width("100%")
106 | .height(320)
107 | .borderRadius(10)
108 | .backgroundColor(item.color)
109 | Text(item.title).fontSize(14).margin({ top: 10, left: 5 })
110 | }.width("100%").alignItems(HorizontalAlign.Start).onClick((e: ClickEvent) => {
111 | router.pushUrl({
112 | url: "pages/SetWallpaper",
113 | params: {
114 | id: item.id
115 | }
116 | })
117 | })
118 | }.alignItems(HorizontalAlign.Start)
119 | }.width("48%").margin({ bottom: 18 })
120 | }, item => item)
121 | }
122 | .columnsTemplate("lfr lfr")
123 | .columnsGap(10)
124 | .rowsGap(10)
125 | .layoutDirection(GridDirection.Row)
126 | .width("90%")
127 | if (this.isLoad) {
128 | PullUp()
129 | }
130 | if (this.isEnd) {
131 | InEnd()
132 | }
133 | }.constraintSize({minHeight:this.hmHeight})
134 | }
135 | .height(this.hmHeight)
136 | .width("100%")
137 | .edgeEffect(EdgeEffect.Spring)
138 | .onScroll(() => {
139 | let y = this.scroller.currentOffset().yOffset
140 | // y 为 负数则为下拉刷新 为正为上拉加载
141 | if (y > 0) {
142 | return
143 | }
144 | this.pull_text = "松开刷新"
145 | const scroll_y = Math.floor(Math.abs(y))
146 | if (scroll_y === 0) {
147 | this.pull_text = "刷新中"
148 | }
149 | // 保持加载的圆形有高度
150 | if (scroll_y > 24) {
151 | this.isPull = true
152 | this.hei = scroll_y
153 | }
154 | })
155 | .onScrollStop(() => {
156 | // 滚动条停止滚动 判断是刷新操作,避免上拉加载执行
157 | if (this.isPull) {
158 | this.pull_text = "刷新中"
159 | this.page.offset = 1
160 | this.getWallpaper()
161 | }
162 | })
163 | .onScrollEdge((side: Edge) => {
164 | // 上拉分页加载
165 | if (Edge.Bottom === side) {
166 | // 分页加载的长度等于总数则不往下执行
167 | if (this.list.length === this.page.count) {
168 | this.isLoad = false
169 | this.isEnd = true
170 | return
171 | }
172 | // 如果当前上拉分页loading状态还未完成,不让其往下 执行
173 | if (this.isLoad) {
174 | return
175 | }
176 | // 分页加一 执行分页加载
177 | this.isLoad = true
178 | this.page.offset++
179 | this.getWallpaper()
180 | }
181 | })
182 | if (this.loading) {
183 | Loading()
184 | }
185 | }.width('100%')
186 | }
187 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/navbar/home_bar.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import { PageInter, WallItemInter } from '../../interface/index'
3 | import { base_url } from '../../utils/env'
4 | import request from '../../utils/http'
5 | import { hmRect, setBgColor, connectNet } from '../../utils/tools'
6 | import { toast } from '../../component/ShowToast'
7 | import Loading from '../../component/Loading'
8 | import NoData from '../../component/NoData'
9 | import connection from '@ohos.net.connection'
10 | import emitter from '@ohos.events.emitter'
11 |
12 | @Component
13 | export default struct HomeBar {
14 | scroller: Scroller = new Scroller()
15 | @State page: PageInter = { offset: 1, limit: 6, count: -1 }
16 | @State list: any = []
17 | @State loading: boolean = false
18 | @State hmHeight: string = "90%";
19 | @State state: number = 0
20 |
21 | async aboutToAppear() {
22 | const hr = await hmRect()
23 | this.hmHeight = hr.hmHeight - 300 + 'px'
24 | this.watchConnect()
25 | let innerEvent = { eventId: 10000 }
26 | emitter.on(innerEvent, this.onEventHandel.bind(this))
27 | }
28 |
29 | async watchConnect() {
30 | this.loading = true
31 | // 监听网络连接状态 模拟器无效 真机正常
32 | const state = await connectNet()
33 | this.state = state
34 | if (state === -1) {
35 | this.loading = false
36 | }
37 | if (state != -1) {
38 | this.getWallpaper()
39 | }
40 | }
41 | // 重新加载数据事件
42 | onEventHandel() {
43 | this.watchConnect()
44 | }
45 | // 壁纸
46 | async getWallpaper() {
47 | try {
48 | this.loading = true
49 | let api = `/api/wallpaper/app/get_wallpaper?offset=${this.page.offset}&limit=${this.page.limit}`
50 | const res: any = await request.post(api)
51 | this.loading = false
52 | if (res.code === 200) {
53 | this.page.count = res.data.count
54 | const rows = setBgColor(res.data.rows)
55 | this.list = [...this.list, ...rows]
56 | } else {
57 | toast.error(res.msg)
58 | }
59 | } catch (err) {
60 | this.loading = false
61 | toast.error()
62 | }
63 | }
64 |
65 | build() {
66 | Column() {
67 | if (this.page.count === 0 || this.state === -1) {
68 | NoData({ type: "page", state: this.state, })
69 | }
70 | WaterFlow({ scroller: this.scroller }) {
71 | ForEach(this.list, (item: WallItemInter, idx: number) => {
72 | FlowItem() {
73 | Column() {
74 | if (idx === 0) {
75 | Row() {
76 | Image($r("app.media.ip_show"))
77 | .width('100%')
78 | .height(50)
79 | .borderRadius(10)
80 | .backgroundColor(0xf3a8ed)
81 | Text("热门IP壁纸").offset({ x: -130, y: 2 }).fontColor(0xffffff)
82 | }.width('100%').height(50).margin({ bottom: 14 }).onClick(() => {
83 | router.pushUrl({
84 | url: "pages/Wallpaper"
85 | })
86 | })
87 | }
88 | Column() {
89 | Image(item.url_type == 0 ? base_url + item.url : item.url)
90 | .width("100%")
91 | .height(300)
92 | .borderRadius(10)
93 | .backgroundColor(item.color)
94 | Text(item.title).fontSize(14).margin({ top: '5' })
95 | }.width("100%").alignItems(HorizontalAlign.Start).onClick((e: ClickEvent) => {
96 | router.pushUrl({
97 | url: "pages/SetWallpaper",
98 | params: {
99 | id: item.id
100 | }
101 | })
102 | })
103 | }.alignItems(HorizontalAlign.Start)
104 | }.width("45%").margin({ bottom: 18 })
105 | }, item => item)
106 | }
107 | .width('90%')
108 | .layoutDirection(FlexDirection.Column)
109 | .columnsTemplate("1fr 1fr")
110 | .columnsGap(16)
111 | .onReachEnd(() => {
112 | if (this.page.count === -1) {
113 | return
114 | }
115 | // 分页加载的长度等于总数则不往下执行
116 | if (this.list.length === this.page.count) {
117 | this.loading = false
118 | return
119 | }
120 | // 如果当前上拉分页loading状态还未完成,不让其往下 执行
121 | if (this.loading) {
122 | return
123 | }
124 | // 分页加一 执行分页加载
125 | this.loading = true
126 | this.page.offset++
127 | this.getWallpaper()
128 | })
129 |
130 | if (this.loading) {
131 | Loading()
132 | }
133 | }.width('100%')
134 | }
135 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/navbar/mine_bar.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import { OpearInter, UinfoInter } from '../../interface/index'
3 | import { base_url } from '../../utils/env'
4 | import request from '../../utils/http'
5 | import { toast } from '../../component/ShowToast'
6 | import { touchBgColor } from '../../utils/tools'
7 | import storage from '../../utils/storage'
8 | @Component
9 | export default struct MineBar {
10 | @State opearList: Array = [
11 | { icon: $r("app.media.order"), title: "我的壁纸", url: "pages/MineWall", touchColor: Color.Transparent },
12 | { icon: $r("app.media.love"), title: "我的收藏", url: "pages/MineCollect", touchColor: Color.Transparent },
13 | { icon: $r("app.media.about"), title: "关于壁纸", url: "pages/AboutUs", touchColor: Color.Transparent },
14 | ]
15 | @State touchBgColor: number[] = [Color.Transparent, Color.Transparent, Color.Transparent]
16 | @State info: UinfoInter = {
17 | avatar: "",
18 | uname: ""
19 | }
20 |
21 | aboutToAppear() {
22 | this.getUserInfo()
23 | }
24 | //个人信息
25 | async getUserInfo() {
26 | try {
27 | const res: any = await request.get("/api/sign/get_user")
28 | if (res.code === 200) {
29 | this.info = res.data
30 | } else {
31 | this.info = {
32 | avatar: "",
33 | uname: ""
34 | }
35 | }
36 | } catch (err) {
37 | toast.error()
38 | }
39 | }
40 | async toLogin(){
41 | try {
42 | await storage.clear()
43 | router.pushUrl({
44 | url: "pages/Sign"
45 | })
46 | }catch (err) {
47 |
48 | }
49 |
50 | }
51 | build() {
52 | Column() {
53 | Flex({
54 | direction: FlexDirection.Column,
55 | justifyContent: FlexAlign.Center,
56 | alignItems: ItemAlign.Center
57 | }) {
58 | Image(this.info.avatar ? base_url + this.info.avatar : $r('app.media.user'))
59 | .width(60)
60 | .height(60)
61 | .borderRadius(60)
62 | .backgroundColor(0xe7e7e7)
63 | Text(this.info.uname ? this.info.uname : '未登录')
64 | .fontWeight(FontWeight.Bold)
65 | .fontSize(18)
66 | .margin({ top: 10 })
67 | }.height(100).margin({ top: 50 }).onClick(() => {
68 | if (this.info.uname) {
69 | router.pushUrl({ url: "pages/UserInfo" })
70 | } else {
71 | router.pushUrl({ url: "pages/Sign" })
72 | }
73 | })
74 |
75 | List() {
76 | ForEach(this.opearList, (item, i: number) => {
77 | ListItem() {
78 | Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
79 | Row() {
80 | Image(item.icon).width(20).height(20)
81 | Text(`${item.title}`).fontSize(14).margin({ left: 14 })
82 | }
83 |
84 | Image($r("app.media.arrow")).width(20).height(20)
85 | }
86 | .width("90%")
87 | .height("100%")
88 | .margin({ left: 10, right: 10 })
89 | }
90 | .height(65)
91 | .width("100%")
92 | .backgroundColor(this.touchBgColor[i])
93 | .onTouch((event) => {
94 | this.touchBgColor[i] = touchBgColor(event) === 0xffffff ? Color.Transparent : touchBgColor(event)
95 | })
96 | .onClick(() => {
97 | router.pushUrl({ url: item.url })
98 | })
99 | })
100 |
101 | }.width("100%").margin({ top: 50 })
102 |
103 | if (this.info.reg_time) {
104 | Button('退出登录', { type: ButtonType.Capsule, stateEffect: true })
105 | .backgroundColor(0xa99ee9)
106 | .width("90%")
107 | .margin({ top: 20 })
108 | .onClick(()=>{
109 | this.toLogin()
110 | })
111 | }
112 | }.justifyContent(FlexAlign.Start).height("100%").width("100%").linearGradient({
113 | direction: GradientDirection.Top,
114 | angle: 180,
115 | colors: [[0xe9e5fb, 0.0], [0xffffff, 0.5], [0xffffff, 1.0]]
116 | })
117 | }
118 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/navbar/sort_bar.ets:
--------------------------------------------------------------------------------
1 | import router from '@ohos.router'
2 | import { PageInter, WallItemInter } from '../../interface/index'
3 | import { base_url } from '../../utils/env'
4 | import request from '../../utils/http'
5 | import Loading from '../../component/Loading'
6 | import NoData from '../../component/NoData'
7 | import { PullUp, PullDown, InEnd } from '../../component/ToLoad'
8 | import { toast } from '../../component/ShowToast'
9 | import { connectNet, hmRect, setBgColor } from '../../utils/tools'
10 | import emitter from '@ohos.events.emitter'
11 |
12 | @Component
13 | export default struct SortBar {
14 | @State list: Array = []
15 | scroller: Scroller = new Scroller()
16 | @State page: PageInter = { offset: 1, limit: 20, count: -1 }
17 | @State loading: boolean = false
18 | @State hmHeight: string = "90%";
19 | @State type_id: string = ""
20 | @State isLoad: boolean = false // 触底分页加载状态
21 | @State isEnd: boolean = false // 到底了没数据了状态
22 | @State hei: number = 25
23 | @State state: number = 0
24 |
25 | async aboutToAppear() {
26 | const hr = await hmRect()
27 | this.hmHeight = hr.hmHeight - 300 + 'px'
28 | this.watchConnect()
29 | let innerEvent = { eventId: 10000 }
30 | emitter.on(innerEvent, this.onEventHandel.bind(this))
31 | }
32 | async watchConnect() {
33 | this.loading = true
34 | // 监听网络连接状态 模拟器无效 真机正常
35 | const state = await connectNet()
36 | this.state = state
37 | if (state === -1) {
38 | this.loading = false
39 | }
40 | if (state != -1) {
41 | this.getWallpaperTypeType(true)
42 | }
43 | }
44 | // 重新加载数据事件
45 | onEventHandel() {
46 | this.watchConnect()
47 | }
48 | // 壁纸分类
49 | async getWallpaperTypeType(flag = false) {
50 | try {
51 | if (flag) {
52 | this.loading = true
53 | }
54 | let api = `/api/wallpaper/app/get_wallpaper_type?offset=${this.page.offset}&limit=${this.page.limit}`
55 | const res: any = await request.post(api)
56 | this.loading = this.isLoad = false
57 | if (res.code === 200) {
58 | this.page.count = res.data.count
59 | const rows = setBgColor(res.data.rows)
60 | this.list = [...this.list, ...rows]
61 | } else {
62 | toast.error(res.msg)
63 | }
64 | } catch (err) {
65 | this.loading = this.isLoad = false
66 | toast.error()
67 | }
68 | }
69 |
70 | build() {
71 | Column() {
72 | if (this.page.count === 0 || this.state === -1) {
73 | NoData({ type: "bar", state: this.state })
74 | }
75 | Scroll(this.scroller) {
76 | Column() {
77 | Grid() {
78 | ForEach(this.list, (item: any) => {
79 | GridItem() {
80 | Stack({ alignContent: Alignment.TopStart }) {
81 | Image(item.cover_type === 0 ? base_url + item.cover_url : item.cover_url)
82 | .borderRadius(12)
83 | .width('100%')
84 | .height(100)
85 | .backgroundColor(item.color)
86 | Text(item.title).fontColor(0xffffffff).fontSize(18).markAnchor({ x: -14, y: -20 })
87 | }.width('48.5%')
88 | }.onClick(() => {
89 | router.pushUrl({
90 | url: "pages/Wallpaper",
91 | params: {
92 | id: item.id
93 | }
94 | })
95 | })
96 | })
97 | }
98 | .columnsTemplate("lfr lfr")
99 | .columnsGap(10)
100 | .rowsGap(10)
101 | .layoutDirection(GridDirection.Row)
102 | .width("90%")
103 |
104 | if (this.isLoad) {
105 | PullUp()
106 | }
107 | if (this.isEnd) {
108 | InEnd()
109 | }
110 | }.constraintSize({ minHeight: this.hmHeight })
111 | }
112 | .height(this.hmHeight)
113 | .width("100%")
114 | .edgeEffect(EdgeEffect.Spring)
115 | .onScrollEdge((side: Edge) => {
116 | // 上拉分页加载
117 | if (Edge.Bottom === side) {
118 | // 分页加载的长度等于总数则不往下执行
119 | if (this.list.length === this.page.count) {
120 | this.isLoad = false
121 | this.isEnd = true
122 | return
123 | }
124 | // 如果当前上拉分页loading状态还未完成,不让其往下 执行
125 | if (this.isLoad) {
126 | return
127 | }
128 | // 分页加一 执行分页加载
129 | this.isLoad = true
130 | this.page.offset++
131 | this.getWallpaperTypeType()
132 | }
133 | })
134 |
135 | if (this.loading) {
136 | Loading()
137 | }
138 | }.width("100%")
139 |
140 | }
141 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/data_source.ets:
--------------------------------------------------------------------------------
1 | export class ListData implements IDataSource {
2 | private list: any = []
3 | private listener: DataChangeListener
4 |
5 | constructor(list: any) {
6 | this.list = list
7 | }
8 |
9 | totalCount(): number {
10 | return this.list.length
11 | }
12 |
13 | getData(index: number): any {
14 | return this.list[index]
15 | }
16 |
17 | registerDataChangeListener(listener: DataChangeListener): void {
18 | this.listener = listener
19 | }
20 |
21 | unregisterDataChangeListener() {
22 | }
23 | public pushData(data: any): void {
24 | this.list.push(data);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/env.ts:
--------------------------------------------------------------------------------
1 | // export const base_url = "http://172.24.48.1"
2 | export const base_url = "https://www.dillonl.com/wapi"
3 |
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/http.ets:
--------------------------------------------------------------------------------
1 | import http from '@ohos.net.http';
2 |
3 | const httpRequest = http.createHttp();
4 | import storage from './storage'
5 | import { base_url } from './env'
6 |
7 | async function create_http(api: string, extraData: any, method: http.RequestMethod) {
8 | const tokens = await storage.get("token")
9 | // 测试使用 5天生效期
10 | let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJiNzcxZjQxOC01MmQxLTRiMDQtOGI1NC0zNDBhMjE5MDdjZTQiLCJwYXNzd29yZCI6ImI0NWNmZmUwODRkZDNkMjBkOTI4YmVlODVlN2IwZjIxIiwiaWF0IjoxNzA1ODM4NjAyLCJleHAiOjE3MDk0MzUwMDJ9.KY00XZ3ImujC33xGyvPsYD_f7Vg1tULb9D68t9nelvY"
11 | return httpRequest.request(base_url + api, {
12 | method,
13 | connectTimeout: 20000,
14 | readTimeout: 20000,
15 | header: {
16 | 'Content-Type': 'application/json',
17 | "Authorization": token ? 'Bearer ' + token : ''
18 | },
19 | extraData,
20 | expectDataType: http.HttpDataType.OBJECT
21 | });
22 | }
23 |
24 | export default {
25 | get: (api) => {
26 | return new Promise((resolve, reject) => {
27 | create_http(api, "", http.RequestMethod.GET).then((response) => {
28 | let result = response.result
29 | resolve(result)
30 | }).catch((error) => {
31 | reject(error)
32 | })
33 | })
34 | },
35 | post: (api, params = {}) => {
36 | return new Promise((resolve, reject) => {
37 | create_http(api, params, http.RequestMethod.POST).then((response) => {
38 | let result = response.result
39 | resolve(result)
40 | }).catch((error) => {
41 | reject(error)
42 | })
43 | })
44 | }
45 | }
46 |
47 |
48 |
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/storage.ets:
--------------------------------------------------------------------------------
1 | import common from '@ohos.app.ability.common';
2 | import data_preferences from '@ohos.data.preferences';
3 | const context = getContext(this) as common.UIAbilityContext;
4 | let promise = data_preferences.getPreferences(context, 'stroage')
5 |
6 | export default {
7 | set: (key: string, value: string): Promise => {
8 | return new Promise((resolve, reject) => {
9 | promise.then((preferences) => {
10 | preferences.put(key, value).then(res => {
11 | console.info("缓存成功");
12 | resolve("")
13 | }).catch((err) => {
14 | console.error("缓存失败:",JSON.stringify(err));
15 | reject(JSON.stringify(err))
16 | })
17 | }).catch((err) => {
18 | console.error("缓存初始化失败:",JSON.stringify(err));
19 | reject(JSON.stringify(err))
20 | })
21 | })
22 | },
23 | get: (key: string): Promise => {
24 | return new Promise((resolve, reject) => {
25 | promise.then((preferences) => {
26 | preferences.get(key,'').then((res:string) => {
27 | resolve(res)
28 | }).catch((err) => {
29 | console.error("获取失败:",JSON.stringify(err));
30 | reject(JSON.stringify(err))
31 | })
32 | }).catch((err) => {
33 | console.error("获取缓存异常:",JSON.stringify(err));
34 | reject(JSON.stringify(err))
35 | })
36 | })
37 | },
38 | clear: (): Promise => {
39 | return new Promise((resolve, reject) => {
40 | promise.then((preferences) => {
41 | preferences.clear().then(() => {
42 | resolve(true)
43 | }).catch((err) => {
44 | reject(JSON.stringify(err))
45 | })
46 | }).catch((err) => {
47 | reject(JSON.stringify(err))
48 | })
49 | })
50 | }
51 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/tools.ets:
--------------------------------------------------------------------------------
1 | import window from '@ohos.window'
2 | import connection from '@ohos.net.connection';
3 |
4 | export const hmRect = async () => {
5 | let win = await window.getLastWindow(getContext(this))
6 | let area: any = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
7 | console.log("设备宽高", JSON.stringify(area));
8 | return {
9 | hmWidth: area.bottomRect.width, // 设备的宽度 px像素
10 | hmHeight: area.bottomRect.top // 设备的高度 px像素
11 | }
12 | }
13 | // 加载图片交互背景 0x 90[颜色透明度] ffc63a[颜色值#ffc63a]
14 | const colorList = [0x90ffc63a, 0x904ad6ee, 0x90d86af3, 0x906af3a7, 0x907c85f3, 0x9058e16e, 0x90f38abc]
15 |
16 | export const setBgColor = (data: any) => {
17 | return data.map((x, i) => {
18 | return { ...x, color: colorList[i%colorList.length] }
19 | })
20 | }
21 | // 手指按下控件背景色交互
22 | export const touchBgColor = (event: any) => {
23 | if (event.type === TouchType.Down) {
24 | return 0xeeeeee
25 | }
26 | if (event.type === TouchType.Up) {
27 | return 0xffffff
28 | }
29 | }
30 |
31 | export const getRandomColor = () => {
32 | const i = Math.round(Math.random() * colorList.length - 1)
33 | return colorList[i]
34 | }
35 |
36 |
37 | // 监听网络状态
38 | export const connectNet = ():Promise => {
39 | let netCon: connection.NetConnection = connection.createNetConnection();
40 | return new Promise((resolve, reject) => {
41 | // 模拟器调试不起作用,真机正常
42 | netCon.register((error) => {
43 | console.log("监听网络状态异常:", JSON.stringify(error))
44 | if(error){
45 | resolve(0)
46 | }else{
47 | resolve(0)
48 | }
49 | })
50 | netCon.on('netAvailable', (data: connection.NetHandle) => {
51 | console.log("网络:",JSON.stringify(data))
52 | resolve(0)
53 | })
54 | })
55 |
56 | }
--------------------------------------------------------------------------------
/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 | ],
10 | "deliveryWithInstall": true,
11 | "installationFree": false,
12 | "pages": "$profile:main_pages",
13 | "abilities": [
14 | {
15 | "name": "EntryAbility",
16 | "srcEntry": "./ets/entryability/EntryAbility.ts",
17 | "description": "$string:EntryAbility_desc",
18 | "icon": "$media:icon",
19 | "label": "$string:EntryAbility_label",
20 | "startWindowIcon": "$media:icon",
21 | "startWindowBackground": "$color:start_window_background",
22 | "exported": true,
23 | "skills": [
24 | {
25 | "entities": [
26 | "entity.system.home"
27 | ],
28 | "actions": [
29 | "action.system.home"
30 | ]
31 | }
32 | ]
33 | }
34 | ],
35 | "requestPermissions": [
36 | {
37 | "name": "ohos.permission.INTERNET"
38 | },
39 | {
40 | "name": "ohos.permission.SET_WALLPAPER"
41 | },
42 | {
43 | "name": "ohos.permission.GET_NETWORK_INFO"
44 | },
45 | {
46 | "name": "ohos.permission.GET_WIFI_INFO"
47 | }
48 | ]
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/color.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": [
3 | {
4 | "name": "start_window_background",
5 | "value": "#FFFFFF"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/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": "label"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/0.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/0_.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/1_.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/2_.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/about.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/arrow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/back.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 | Public/ic_public_back
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/delete.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 | Public/ic_public_delete
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/entry/src/main/resources/base/media/icon.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ip_show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/entry/src/main/resources/base/media/ip_show.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/entry/src/main/resources/base/media/loading.gif
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/love.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/love_red.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/love_white.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/man.svg:
--------------------------------------------------------------------------------
1 |
7 |
10 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/nodata.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/order.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/woman.svg:
--------------------------------------------------------------------------------
1 |
8 |
11 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/profile/main_pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": [
3 | "pages/Index",
4 | "pages/Sign",
5 | "pages/SetWallpaper",
6 | "pages/UserInfo",
7 | "pages/Wallpaper",
8 | "pages/MineCollect",
9 | "pages/MineWall",
10 | "pages/AboutUs"
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": "label"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/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": "壁纸小屋,壁纸"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "壁纸小屋"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/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 | ],
10 | "deliveryWithInstall": true,
11 | "installationFree": false,
12 | "pages": "$profile:test_pages",
13 | "abilities": [
14 | {
15 | "name": "TestAbility",
16 | "srcEntry": "./ets/testability/TestAbility.ets",
17 | "description": "$string:TestAbility_desc",
18 | "icon": "$media:icon",
19 | "label": "$string:TestAbility_label",
20 | "exported": true,
21 | "startWindowIcon": "$media:icon",
22 | "startWindowBackground": "$color:start_window_background",
23 | "skills": [
24 | {
25 | "actions": [
26 | "action.system.home"
27 | ],
28 | "entities": [
29 | "entity.system.home"
30 | ]
31 | }
32 | ]
33 | }
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/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/dlongs49/wallpaper-app/ef84f33ba56fbe333c50c0de59ae56d28f556c0b/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 | "hvigorVersion": "2.4.2",
3 | "dependencies": {
4 | "@ohos/hvigor-ohos-plugin": "2.4.2"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/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';
--------------------------------------------------------------------------------
/hvigorw:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # ----------------------------------------------------------------------------
4 | # Hvigor startup script, version 1.0.0
5 | #
6 | # Required ENV vars:
7 | # ------------------
8 | # NODE_HOME - location of a Node home dir
9 | # or
10 | # Add /usr/local/nodejs/bin to the PATH environment variable
11 | # ----------------------------------------------------------------------------
12 |
13 | HVIGOR_APP_HOME=$(dirname $(readlink -f $0))
14 | HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
15 | warn() {
16 | echo ""
17 | echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
18 | }
19 |
20 | error() {
21 | echo ""
22 | echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
23 | }
24 |
25 | fail() {
26 | error "$@"
27 | exit 1
28 | }
29 |
30 | # Determine node to start hvigor wrapper script
31 | if [ -n "${NODE_HOME}" ];then
32 | EXECUTABLE_NODE="${NODE_HOME}/bin/node"
33 | if [ ! -x "$EXECUTABLE_NODE" ];then
34 | fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
35 | fi
36 | else
37 | EXECUTABLE_NODE="node"
38 | which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
39 | fi
40 |
41 | # Check hvigor wrapper script
42 | if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
43 | fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
44 | fi
45 |
46 | # start hvigor-wrapper script
47 | exec "${EXECUTABLE_NODE}" \
48 | "${HVIGOR_WRAPPER_SCRIPT}" "$@"
49 |
--------------------------------------------------------------------------------
/hvigorw.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Hvigor startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
17 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
18 |
19 | set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
20 | set NODE_EXE=node.exe
21 |
22 | goto start
23 |
24 | :start
25 | @rem Find node.exe
26 | if defined NODE_HOME goto findNodeFromNodeHome
27 |
28 | %NODE_EXE% --version >NUL 2>&1
29 | if "%ERRORLEVEL%" == "0" goto execute
30 |
31 | echo.
32 | echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
33 | echo.
34 | echo Please set the NODE_HOME variable in your environment to match the
35 | echo location of your NodeJs installation.
36 |
37 | goto fail
38 |
39 | :findNodeFromNodeHome
40 | set NODE_HOME=%NODE_HOME:"=%
41 | set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
42 |
43 | if exist "%NODE_EXE_PATH%" goto execute
44 | echo.
45 | echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
46 | echo.
47 | echo Please set the NODE_HOME variable in your environment to match the
48 | echo location of your NodeJs installation.
49 |
50 | goto fail
51 |
52 | :execute
53 | @rem Execute hvigor
54 | "%NODE_EXE%" %WRAPPER_MODULE_PATH% %*
55 |
56 | if "%ERRORLEVEL%" == "0" goto hvigorwEnd
57 |
58 | :fail
59 | exit /b 1
60 |
61 | :hvigorwEnd
62 | if "%OS%" == "Windows_NT" endlocal
63 |
64 | :end
65 |
--------------------------------------------------------------------------------
/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 | },
7 | "packages": {
8 | "@ohos/hypium@1.0.6": {
9 | "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
10 | "integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ=="
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "license": "MIT",
3 | "devDependencies": {
4 | "@ohos/hypium": "1.0.6"
5 | },
6 | "author": "dinglong",
7 | "name": "wallpaper_app",
8 | "description": "A wallpaper Settings app",
9 | "main": "",
10 | "version": "1.0.0",
11 | "dependencies": {}
12 | }
13 |
--------------------------------------------------------------------------------