├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── LICENSE ├── README.md ├── cloudfunctions ├── analyse │ ├── config.json │ ├── index.js │ ├── package-lock.json │ └── package.json ├── getOpenId │ ├── config.json │ ├── index.js │ └── package.json ├── get_wx_context │ ├── index.js │ └── package.json └── msg_sec_check │ ├── config.json │ ├── index.js │ └── package.json ├── image ├── WeHalo.png ├── alipay.png ├── demo.png ├── logo-jb.svg ├── wechat.png ├── wehalo.jpg └── wx.png ├── miniprogram ├── app.js ├── app.json ├── app.wxss ├── colorui │ ├── animation.wxss │ ├── components │ │ ├── cu-custom.js │ │ ├── cu-custom.json │ │ ├── cu-custom.wxml │ │ └── cu-custom.wxss │ ├── icon.wxss │ └── main.wxss ├── components │ ├── addTips │ │ ├── wh-addTips.js │ │ ├── wh-addTips.json │ │ ├── wh-addTips.wxml │ │ └── wh-addTips.wxss │ ├── authorCard │ │ ├── wh-authorCard.js │ │ ├── wh-authorCard.json │ │ ├── wh-authorCard.wxml │ │ └── wh-authorCard.wxss │ └── typeWriter │ │ ├── wh-typeWriter.js │ │ ├── wh-typeWriter.json │ │ ├── wh-typeWriter.wxml │ │ └── wh-typeWriter.wxss ├── image │ ├── cat.png │ ├── video-image │ │ ├── logo-douyin.png │ │ ├── logo-gitShow.png │ │ ├── logo-microview.png │ │ ├── logo-ppx.png │ │ └── logo-zuiyou.png │ └── wave.gif ├── pages │ ├── friends │ │ ├── friends.js │ │ ├── friends.json │ │ ├── friends.wxml │ │ └── friends.wxss │ ├── halo │ │ ├── halo.js │ │ ├── halo.json │ │ ├── halo.wxml │ │ └── halo.wxss │ ├── index │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── journal │ │ ├── journal.js │ │ ├── journal.json │ │ ├── journal.wxml │ │ └── journal.wxss │ ├── photos │ │ ├── photos.js │ │ ├── photos.json │ │ ├── photos.wxml │ │ └── photos.wxss │ ├── post │ │ ├── post.js │ │ ├── post.json │ │ ├── post.wxml │ │ └── post.wxss │ └── wehalo │ │ ├── wehalo.js │ │ ├── wehalo.json │ │ ├── wehalo.wxml │ │ └── wehalo.wxss ├── sitemap.json └── utils │ ├── jinrishici.js │ ├── request.js │ └── util.js └── project.config.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://afdian.net/@saving', 'https://raw.githubusercontent.com/aquanlerou/WeHalo/master/image/alipay.png', 'https://raw.githubusercontent.com/aquanlerou/WeHalo/master/image/wechat.png'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://raw.githubusercontent.com/aquanlerou/WeHalo/master/image/wehalo.jpg)](https://github.com/aquanlerou/WeHalo) 2 | 3 | ## WeHalo 支持最新版本 Halo 4 | 5 | 大家的支持,鼓励,认可,是我坚持开源的动力,虽然后面开发完有点拖拉,请原谅 ~ 渲染图在设计中 6 | 7 | 后续更多功能开发并开发给大家使用,新版本 **WeHalo** 会存在不少问题欢迎大家多给我提 **Issues** 我会尽快处理 8 | 9 | 新版本使用的问题不懂可以通过小程序联系作者找到我或者添加 10 | 11 | > ✍ Halo 一款现代化的个人独立博客系统 [Halo](https://halo.run) 12 | 13 | [![Github](https://img.shields.io/badge/Author-Aquan-FF4500.svg?style=flat-square)](https://github.com/aquanlerou) 14 | [![GitHub release](https://img.shields.io/github/release/aquanlerou/WeHalo.svg?style=flat-square)](https://github.com/aquanlerou/WeHalo/releases) 15 | [![](https://img.shields.io/github/languages/code-size/aquanlerou/WeHalo.svg?style=flat-square)](https://github.com/aquanlerou/WeHalo) 16 | [![GitHub LICENSE](https://img.shields.io/github/license/aquanlerou/WeHalo.svg?style=flat-square)](https://github.com/aquanlerou/WeHalo/blob/master/LICENSE) 17 | [![star](https://img.shields.io/github/stars/aquanlerou/WeHalo.svg?label=Stars&style=social)](https://github.com/aquanlerou/WeHalo) 18 | [![star](https://gitee.com/aquanrun/WeHalo/badge/star.svg?theme=white)](https://gitee.com/aquanrun/WeHalo/stargazers) 19 | 20 | ------------------------------ 21 | 22 |
目录 23 | 24 | - [简介](#简介) 25 | - [快速开始](#快速开始) 26 | - [文档](#文档) 27 | - [演示](#演示) 28 | - [许可证](#许可证) 29 | - [后续功能](#后续功能) 30 | - [感谢](#感谢) 31 | - [捐赠](#捐赠) 32 | 33 |
34 | 35 | ## 简介 36 | 37 | **WeHalo** [wiˈheɪloʊ],意为我们的光环,嘻嘻。 38 | 39 | 配合 [**Halo**](https://github.com/halo-dev/halo) 轻快,简洁,功能强大的博客系统而开发出来的 **简约风** 微信小程序版博客 40 | 41 | ## 快速开始 42 | 43 | **注:开源不易请留 WeHalo 底部署名不要删除** 44 | 45 | ```bash 46 | git clone https://github.com/savingrun/WeHalo.git 47 | ``` 48 | 49 | 代码下载后,把 **image** 文件夹删除(放的是README中的图片与项目无关),用小程序 IDE 打开后即可使用。 50 | 51 | **注:请选择小程序项目,非小游戏,例子中无 appid,所以无法在手机上运行,如果需要真机调试,请在打开例子时,填上自己的小程序 id** 52 | 53 | 54 | ## 文档 55 | 56 | 修改``app.js``文件的全局变量,改为你的 **Halo** 博客的地址,请更新最新的 **Halo** 配合使用 57 | 58 | **注:必须是HTTPS的因为,微信官方规定,还有把你的博客地址``如:https://savingrun.one``和``https://v2.jinrishici.com``添加到微信公众平台的 ``request 合法域名``中** 59 | 60 | ``` 61 | globalData: { //全局变量 62 | userInfo: null, 63 | skin: null, 64 | roleFlag: false, 65 | BlogName: "爱敲代码的猫",//博客名字 66 | url: "https://savingrun.one",//博客地址(需HTTPS) 67 | token: "",//Halo博客后台设置 68 | highlightStyle: "dracula",//代码高亮样式,可用值default,darcula,dracula,tomorrow 69 | adminOpenid: "ogogn47AhczrMBgcTCPbUwugqLcU",//导入项目后可以在Console中看到 openidCloudResult: xxxxxxx (xxx就是adminOpenid) 70 | HaloUser: "xx",//Halo后台用户名 71 | HaloPassword: "xx",//Halo后台密码 72 | } 73 | ``` 74 | 75 | **注: 76 | 关于新版本 ``WeHalo`` 找不到 ``adminOpenid`` 的处理方法: ``https://gitee.com/aquanrun/WeHalo/issues/I12J1G``** 77 | 78 | 设置个人专属**Logo** 修改 ``WeHalo\miniprogram\colorui\main.wxss`` 文件最后面的 79 | 80 | ``` 81 | .home-img{ 82 | padding: 24rpx; 83 | background-repeat: no-repeat; 84 | background-size: contain; 85 | /* background-image:url(../image/cat.png); */ 86 | background-image:url('xxxxx');//logo图片地址 87 | } 88 | ``` 89 | 90 | 91 | html2wxml插件版本准备 92 | 93 | > 1. 添加插件 94 | ![添加小程序插件](https://www.qwqoffice.com/html2wxml/images/plugin-1.png "添加小程序插件") 95 | > 2. 搜索 `html2wxml` ,选中并添加 96 | ![添加小程序插件](https://www.qwqoffice.com/html2wxml/images/plugin-2.png "添加小程序插件") 97 | > 3. 添加成功 98 | ![添加小程序插件](https://www.qwqoffice.com/html2wxml/images/plugin-3.png "添加小程序插件") 99 | 100 | 101 | > 文档正在不断完善中,遇到问题请加群提问或者 [**Issues**](https://github.com/aquanlerou/WeHalo/issues) 等你吐槽... 102 | 103 | 104 | ## 演示 105 | 106 | ![WeHalo](https://github.com/aquanlerou/WeHalo/blob/master/image/wx.png) 107 | 108 | #### [**更多演示**](https://github.com/aquanlerou/WeHalo/issues/53) 109 | 110 | 111 | ## 许可证 112 | 113 | [![GitHub LICENSE](https://img.shields.io/github/license/aquanlerou/WeHalo.svg?style=flat-square)](https://github.com/aquanlerou/WeHalo/blob/master/LICENSE) 114 | 115 | > WeHalo使用GPL-v3.0协议开源,请尽量遵守开源协议,即便是在中国。 116 | 117 | ## 功能 118 | 119 | - [x] 重新设计**WeHalo** 120 | - [x] 自定义导航栏(个人觉得好看可自定义) 121 | - [x] 个人名片(可宣传自己) 122 | - [x] 博文展示 123 | - [x] 评论展示 124 | - [x] 搜索文章功能 125 | - [x] 文章评论功能 126 | - [x] 博主查看评论功能 127 | - [x] 博主回复评论功能 128 | - [x] 评论功能内容识别 129 | - [x] 友链展示 130 | - [x] 日记本 131 | - [ ] 点赞功能(云函数) 132 | - [ ] 文章浏览统计功能(云函数) 133 | - [ ] 用户回复评论追评功能 134 | - [ ] 生成海报(微信朋友圈装X) 135 | - [x] 图库展示([小熊随笔](https://www.xtyu.top/)贡献开发) 136 | - [x] 图库图片上传([小熊随笔](https://www.xtyu.top/)贡献开发) 137 | - [x] 短视频去水印([小熊随笔](https://www.xtyu.top/)贡献开发) 138 | - [x] 按类别导航([小熊随笔](https://www.xtyu.top/)贡献开发) 139 | - [x] 加密分类限制([小熊随笔](https://www.xtyu.top/)贡献开发) 140 | - [ ] 想到就写... 141 | 142 | ## 感谢 143 | 144 | WeHalo的诞生离不开下面这些项目的支持: 145 | 146 | - **[Halo](https://github.com/halo-dev/halo): 一个优秀的开源博客发布应用。** 147 | - **[ColorUI](https://github.com/weilanwl/ColorUI):鲜亮的高饱和色彩,专注视觉的小程序组件库** 148 | - **[iView Weapp](https://github.com/TalkingData/iview-weapp):一套高质量的微信小程序 UI 组件库** 149 | - **[Painter](https://github.com/Kujiale-Mobile/Painter):微信小程序生成图片库,绘制一张可以发到朋友圈的图片** 150 | - **[html2wxml](https://github.com/qwqoffice/html2wxml):用于微信小程序的HTML和Markdown格式的富文本渲染组件,支持代码高亮** 151 | - **[一言·古诗词](https://github.com/xenv/gushici):Hitokoto API,随机返回一条古诗词名句。采用 Vert.x + Redis 全异步开发,毫秒级稳定响应。** 152 | 153 | [![](https://raw.githubusercontent.com/savingrun/WeHalo/master/image/logo-jb.svg)](https://www.jetbrains.com) 154 | 155 | > 156 | > 各位的哇哈哈,再次感谢各位的支持 157 | > 158 | 159 | ## Stargazers over time 160 | [![Stargazers over time](https://starchart.cc/aquanlerou/WeHalo.svg)](https://starchart.cc/aquanlerou/WeHalo) 161 | 162 | ## Thanks to all the people who already contributed! 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /cloudfunctions/analyse/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/analyse/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境 3 | var req = require("request-promise"); 4 | 5 | exports.main = async (event, context) => { 6 | console.log(event.url); 7 | const url = event.url; 8 | var options = { 9 | method: 'GET', 10 | uri: url, 11 | json: true // Automatically stringifies the body to JSON 12 | }; 13 | return req(options).then(function (parsedBody) { 14 | console.log(parsedBody.message); 15 | return parsedBody; 16 | }).catch(function (err) { 17 | return err; 18 | }); 19 | } -------------------------------------------------------------------------------- /cloudfunctions/analyse/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "analyse", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "request": "^2.88.2", 13 | "request-promise": "^4.2.6", 14 | "wx-server-sdk": "~2.6.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cloudfunctions/getOpenId/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | "wxacode.get" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /cloudfunctions/getOpenId/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | 3 | cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) 4 | 5 | exports.main = async (event, context) => { 6 | const wxContext = cloud.getWXContext() 7 | 8 | return { 9 | event, 10 | openid: wxContext.OPENID, 11 | appid: wxContext.APPID, 12 | unionid: wxContext.UNIONID, 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/getOpenId/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "getOpenId", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.6.3" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/get_wx_context/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | 3 | cloud.init() 4 | 5 | exports.main = async (event, context) => { 6 | const wxContext = cloud.getWXContext() 7 | 8 | return { 9 | event, 10 | openid: wxContext.OPENID, 11 | appid: wxContext.APPID, 12 | unionid: wxContext.UNIONID, 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/get_wx_context/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get_wx_context", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "latest" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/msg_sec_check/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | "openapi.security.msgSecCheck" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /cloudfunctions/msg_sec_check/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | 3 | cloud.init() 4 | 5 | exports.main = async (event, context) => { 6 | try { 7 | const res = await cloud.openapi.security.msgSecCheck({ 8 | content: event.content 9 | }) 10 | return res; 11 | } catch (err) { 12 | return err; 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/msg_sec_check/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "msg_sec_check", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "latest" 13 | } 14 | } -------------------------------------------------------------------------------- /image/WeHalo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/WeHalo.png -------------------------------------------------------------------------------- /image/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/alipay.png -------------------------------------------------------------------------------- /image/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/demo.png -------------------------------------------------------------------------------- /image/logo-jb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /image/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/wechat.png -------------------------------------------------------------------------------- /image/wehalo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/wehalo.jpg -------------------------------------------------------------------------------- /image/wx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/image/wx.png -------------------------------------------------------------------------------- /miniprogram/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function() { 4 | if (!wx.cloud) { 5 | console.error('请使用 2.2.3 或以上的基础库以使用云能力') 6 | } 7 | else { 8 | wx.cloud.init({ 9 | env: 'xlr-0053be', 10 | traceUser: true, 11 | }) 12 | } 13 | 14 | // 展示本地存储能力 15 | var logs = wx.getStorageSync('logs') || [] 16 | logs.unshift(Date.now()) 17 | wx.setStorageSync('logs', logs) 18 | 19 | // 登录 20 | wx.login({ 21 | success: res => { 22 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 23 | } 24 | }) 25 | // 获取系统状态栏信息 26 | wx.getSystemInfo({ 27 | success: e => { 28 | this.globalData.StatusBar = e.statusBarHeight; 29 | let custom = wx.getMenuButtonBoundingClientRect(); 30 | this.globalData.Custom = custom; 31 | this.globalData.CustomBar = custom.bottom + custom.top - e.statusBarHeight; 32 | } 33 | }) 34 | 35 | const miniProgram = wx.getAccountInfoSync() 36 | console.log(miniProgram) 37 | this.globalData.miniProgram = miniProgram.miniProgram 38 | 39 | // 获取小程序更新机制兼容 40 | if (wx.canIUse('getUpdateManager')) { 41 | const updateManager = wx.getUpdateManager() 42 | updateManager.onCheckForUpdate(function (res) { 43 | // 请求完新版本信息的回调 44 | if (res.hasUpdate) { 45 | updateManager.onUpdateReady(function () { 46 | wx.showModal({ 47 | title: '更新提示', 48 | content: '新版本已经准备好,是否重启应用?', 49 | success: function (res) { 50 | if (res.confirm) { 51 | // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 52 | updateManager.applyUpdate() 53 | } 54 | } 55 | }) 56 | }) 57 | updateManager.onUpdateFailed(function () { 58 | // 新的版本下载失败 59 | wx.showModal({ 60 | title: '已经有新版本了哟~', 61 | content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~', 62 | }) 63 | }) 64 | } 65 | }) 66 | } else { 67 | // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示 68 | wx.showModal({ 69 | title: '提示', 70 | content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' 71 | }) 72 | } 73 | 74 | }, 75 | globalData: { //全局变量 76 | userInfo: null, 77 | skin: null, 78 | roleFlag: false, 79 | url: "xxx",//http://localhost:8090 80 | BlogName: "xxx", 81 | token: "xxx", 82 | highlightStyle: "dracula", //代码高亮样式,可用值default,darcula,dracula,tomorrow 83 | adminOpenid: "xxx", 84 | HaloUser: "xxx", 85 | HaloPassword: "xxxxx" 86 | } 87 | 88 | }) -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/wehalo/wehalo", 5 | "pages/halo/halo", 6 | "pages/post/post", 7 | "pages/friends/friends", 8 | "pages/journal/journal", 9 | "pages/photos/photos" 10 | ], 11 | "window": { 12 | "backgroundTextStyle": "light", 13 | "navigationBarBackgroundColor": "#fff", 14 | "navigationBarTitleText": "ColorUI", 15 | "navigationStyle": "custom", 16 | "navigationBarTextStyle": "white" 17 | }, 18 | "usingComponents": { 19 | "cu-custom": "/colorui/components/cu-custom", 20 | "wh-typeWriter": "/components/typeWriter/wh-typeWriter", 21 | "wh-authorCard": "/components/authorCard/wh-authorCard", 22 | "wh-addTips": "/components/addTips/wh-addTips" 23 | }, 24 | "plugins": { 25 | "htmltowxml": { 26 | "version": "1.4.0", 27 | "provider": "wxa51b9c855ae38f3c" 28 | } 29 | }, 30 | "sitemapLocation": "sitemap.json" 31 | } -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | @import "colorui/main.wxss"; 2 | @import "colorui/icon.wxss"; 3 | -------------------------------------------------------------------------------- /miniprogram/colorui/animation.wxss: -------------------------------------------------------------------------------- 1 | /* 2 | Animation 微动画 3 | 基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28 4 | */ 5 | 6 | /* css 滤镜 控制黑白底色gif的 */ 7 | .gif-black{ 8 | mix-blend-mode: screen; 9 | } 10 | .gif-white{ 11 | mix-blend-mode: multiply; 12 | } 13 | 14 | 15 | /* Animation css */ 16 | [class*=animation-] { 17 | animation-duration: .5s; 18 | animation-timing-function: ease-out; 19 | animation-fill-mode: both 20 | } 21 | 22 | .animation-fade { 23 | animation-name: fade; 24 | animation-duration: .8s; 25 | animation-timing-function: linear 26 | } 27 | 28 | .animation-scale-up { 29 | animation-name: scale-up 30 | } 31 | 32 | .animation-scale-down { 33 | animation-name: scale-down 34 | } 35 | 36 | .animation-slide-top { 37 | animation-name: slide-top 38 | } 39 | 40 | .animation-slide-bottom { 41 | animation-name: slide-bottom 42 | } 43 | 44 | .animation-slide-left { 45 | animation-name: slide-left 46 | } 47 | 48 | .animation-slide-right { 49 | animation-name: slide-right 50 | } 51 | 52 | .animation-shake { 53 | animation-name: shake 54 | } 55 | 56 | .animation-reverse { 57 | animation-direction: reverse 58 | } 59 | 60 | @keyframes fade { 61 | 0% { 62 | opacity: 0 63 | } 64 | 65 | 100% { 66 | opacity: 1 67 | } 68 | } 69 | 70 | @keyframes scale-up { 71 | 0% { 72 | opacity: 0; 73 | transform: scale(.2) 74 | } 75 | 76 | 100% { 77 | opacity: 1; 78 | transform: scale(1) 79 | } 80 | } 81 | 82 | @keyframes scale-down { 83 | 0% { 84 | opacity: 0; 85 | transform: scale(1.8) 86 | } 87 | 88 | 100% { 89 | opacity: 1; 90 | transform: scale(1) 91 | } 92 | } 93 | 94 | @keyframes slide-top { 95 | 0% { 96 | opacity: 0; 97 | transform: translateY(-100%) 98 | } 99 | 100 | 100% { 101 | opacity: 1; 102 | transform: translateY(0) 103 | } 104 | } 105 | 106 | @keyframes slide-bottom { 107 | 0% { 108 | opacity: 0; 109 | transform: translateY(100%) 110 | } 111 | 112 | 100% { 113 | opacity: 1; 114 | transform: translateY(0) 115 | } 116 | } 117 | 118 | @keyframes shake { 119 | 120 | 0%, 121 | 100% { 122 | transform: translateX(0) 123 | } 124 | 125 | 10% { 126 | transform: translateX(-9px) 127 | } 128 | 129 | 20% { 130 | transform: translateX(8px) 131 | } 132 | 133 | 30% { 134 | transform: translateX(-7px) 135 | } 136 | 137 | 40% { 138 | transform: translateX(6px) 139 | } 140 | 141 | 50% { 142 | transform: translateX(-5px) 143 | } 144 | 145 | 60% { 146 | transform: translateX(4px) 147 | } 148 | 149 | 70% { 150 | transform: translateX(-3px) 151 | } 152 | 153 | 80% { 154 | transform: translateX(2px) 155 | } 156 | 157 | 90% { 158 | transform: translateX(-1px) 159 | } 160 | } 161 | 162 | @keyframes slide-left { 163 | 0% { 164 | opacity: 0; 165 | transform: translateX(-100%) 166 | } 167 | 168 | 100% { 169 | opacity: 1; 170 | transform: translateX(0) 171 | } 172 | } 173 | 174 | @keyframes slide-right { 175 | 0% { 176 | opacity: 0; 177 | transform: translateX(100%) 178 | } 179 | 180 | 100% { 181 | opacity: 1; 182 | transform: translateX(0) 183 | } 184 | } -------------------------------------------------------------------------------- /miniprogram/colorui/components/cu-custom.js: -------------------------------------------------------------------------------- 1 | const app = getApp(); 2 | Component({ 3 | /** 4 | * 组件的一些选项 5 | */ 6 | options: { 7 | addGlobalClass: true, 8 | multipleSlots: true 9 | }, 10 | /** 11 | * 组件的对外属性 12 | */ 13 | properties: { 14 | bgColor: { 15 | type: String, 16 | default: '' 17 | }, 18 | isCustom: { 19 | type: [Boolean, String], 20 | default: false 21 | }, 22 | isBack: { 23 | type: [Boolean, String], 24 | default: false 25 | }, 26 | bgImage: { 27 | type: String, 28 | default: '' 29 | }, 30 | }, 31 | /** 32 | * 组件的初始数据 33 | */ 34 | data: { 35 | StatusBar: app.globalData.StatusBar, 36 | CustomBar: app.globalData.CustomBar, 37 | Custom: app.globalData.Custom 38 | }, 39 | /** 40 | * 组件的方法列表 41 | */ 42 | methods: { 43 | BackPage() { 44 | wx.navigateBack({ 45 | delta: 1 46 | }); 47 | }, 48 | toHome(){ 49 | wx.reLaunch({ 50 | url: '/pages/index/index', 51 | }) 52 | } 53 | } 54 | }) -------------------------------------------------------------------------------- /miniprogram/colorui/components/cu-custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/colorui/components/cu-custom.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /miniprogram/colorui/components/cu-custom.wxss: -------------------------------------------------------------------------------- 1 | /* colorui/components/cu-custom.wxss */ -------------------------------------------------------------------------------- /miniprogram/components/addTips/wh-addTips.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | text: { 4 | type: String, 5 | value: '点击「添加到我的小程序」' 6 | }, 7 | duration: { 8 | type: Number, 9 | value: 5 10 | } 11 | }, 12 | data: { 13 | SHOW_TOP: false, 14 | SHOW_MODAL: false 15 | }, 16 | ready: function () { 17 | this.setData({ 18 | SHOW_TOP: true 19 | }); 20 | setTimeout(() => { 21 | this.setData({ 22 | SHOW_TOP: false 23 | }) 24 | }, this.data.duration * 1000); 25 | }, 26 | methods: {} 27 | }) -------------------------------------------------------------------------------- /miniprogram/components/addTips/wh-addTips.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/components/addTips/wh-addTips.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{text}} 6 | 7 | -------------------------------------------------------------------------------- /miniprogram/components/addTips/wh-addTips.wxss: -------------------------------------------------------------------------------- 1 | /* components/addTips/wh-addTips.wxss */ 2 | .box { 3 | position: fixed; 4 | top: 130rpx; 5 | /* left: 0; */ 6 | right: 0; 7 | z-index: 999; 8 | display: flex; 9 | justify-content: flex-end; 10 | align-items: flex-end; 11 | flex-direction: column; 12 | width: 600rpx; 13 | } 14 | .arrow { 15 | width: 0; 16 | height: 0; 17 | margin-right: 120rpx; 18 | border-width: 20rpx; 19 | border-style: solid; 20 | border-color: transparent transparent #59b4ff transparent; 21 | } 22 | .body { 23 | background-color: #59b4ff; 24 | box-shadow: 0 10rpx 20rpx -10rpx #59b4ff; 25 | border-radius: 12rpx; 26 | display: flex; 27 | align-items: center; 28 | justify-content: center; 29 | height: 84rpx; 30 | padding: 0 20rpx; 31 | margin-right: 40rpx; 32 | } 33 | .body > text { 34 | color: #FFF; 35 | font-size: 28rpx; 36 | font-weight: 400; 37 | } -------------------------------------------------------------------------------- /miniprogram/components/authorCard/wh-authorCard.js: -------------------------------------------------------------------------------- 1 | // components/authorCard/wh-authorCard.js 2 | Component({ 3 | properties: { 4 | isHidden: { 5 | type: [Boolean, String], 6 | default: true 7 | } 8 | }, 9 | data: { 10 | 11 | }, 12 | methods: { 13 | prevent() { 14 | console.log("防止冒泡"); 15 | var self = this; 16 | wx.setClipboardData({ 17 | data: "https://github.com/aquanlerou" 18 | }); 19 | 20 | }, 21 | showMask() { 22 | this.setData({ 23 | isHidden: false, 24 | }); 25 | var animation = wx.createAnimation({ 26 | duration: 1000, 27 | timingFunction: 'ease', 28 | delay: 0 29 | }); 30 | animation.opacity(1).translate(wx.getSystemInfoSync().windowWidth, 0).step() 31 | this.setData({ 32 | ani: animation.export() 33 | }) 34 | }, 35 | closeMask() { 36 | var that = this; 37 | var animation = wx.createAnimation({ 38 | duration: 1000, 39 | timingFunction: 'ease', 40 | delay: 0 41 | }); 42 | animation.opacity(0).translate(-wx.getSystemInfoSync().windowWidth, 0).step() 43 | that.setData({ 44 | ani: animation.export() 45 | }); 46 | 47 | setTimeout(function () { 48 | that.setData({ 49 | isHidden: true, 50 | }); 51 | }, 600); 52 | } 53 | }, 54 | lifetimes: { 55 | attached: function () { 56 | this.setData({ 57 | isHidden: true, 58 | }); 59 | }, 60 | detached: function () {}, 61 | }, 62 | }) 63 | -------------------------------------------------------------------------------- /miniprogram/components/authorCard/wh-authorCard.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/components/authorCard/wh-authorCard.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/components/authorCard/wh-authorCard.wxss: -------------------------------------------------------------------------------- 1 | /* components/authorCard/wh-authorCard.wxss */ 2 | 3 | .mask { 4 | position: fixed; 5 | left: 0; 6 | top: 0; 7 | right: 0; 8 | bottom: 0; 9 | background: rgba(0, 0, 0, 0.5); 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | flex-direction: column; 14 | z-index: 1030; 15 | } 16 | 17 | .masks { 18 | width: 100%; 19 | /* background-color: white; */ 20 | position: absolute; 21 | left: -100%; 22 | opacity: 0; 23 | text-align: center; 24 | } 25 | 26 | .maskImg { 27 | width: 30%; 28 | float: left; 29 | } 30 | 31 | .box { 32 | display: flex; 33 | align-items: center; 34 | height: 300rpx; 35 | padding: 20rpx; 36 | } 37 | 38 | .left { 39 | width: 35%; 40 | height: 100%; 41 | border-radius: 20rpx; 42 | } 43 | 44 | .leftImage { 45 | width: 300rpx; 46 | border-radius: 12rpx; 47 | } 48 | 49 | .right { 50 | width: 65%; 51 | height: 230rpx; 52 | background-color: #fff; 53 | border: 4rpx solid #e6e6e6; 54 | border-radius: 0 20rpx 20rpx 0; 55 | } 56 | 57 | .info { 58 | text-align: left; 59 | padding-left: 20rpx; 60 | } 61 | 62 | .field { 63 | color: #b6b6b6; 64 | font-size: 24rpx; 65 | } 66 | 67 | .value { 68 | font-size: 29rpx; 69 | margin: 8rpx; 70 | } 71 | 72 | .title { 73 | font-family: 微软雅黑; 74 | line-height: 1.15; 75 | font-weight: 800; 76 | text-rendering: optimizeLegibility; 77 | margin: 14rpx; 78 | } 79 | 80 | .name { 81 | font-size:34rpx; 82 | } 83 | -------------------------------------------------------------------------------- /miniprogram/components/typeWriter/wh-typeWriter.js: -------------------------------------------------------------------------------- 1 | // components/typeWriter/wh-typeWriter.js 2 | Component({ 3 | properties: { 4 | whContent: { 5 | type: String, 6 | default: ' ' 7 | }, 8 | }, 9 | data: { 10 | }, 11 | methods: { 12 | }, 13 | lifetimes: { 14 | attached: function () {}, 15 | detached: function () {}, 16 | ready: function () { 17 | var that = this 18 | var story = this.data.whContent; 19 | var i = 0; 20 | var time = setInterval(function () { 21 | var text = story.substring(0, i); 22 | i++; 23 | that.setData({ 24 | whContent: text 25 | }); 26 | if (text.length == story.length) { 27 | // console.log("定时器结束!"); 28 | clearInterval(time); 29 | } 30 | }, 200) 31 | }, 32 | }, 33 | }) 34 | -------------------------------------------------------------------------------- /miniprogram/components/typeWriter/wh-typeWriter.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/components/typeWriter/wh-typeWriter.wxml: -------------------------------------------------------------------------------- 1 | {{whContent}} -------------------------------------------------------------------------------- /miniprogram/components/typeWriter/wh-typeWriter.wxss: -------------------------------------------------------------------------------- 1 | /* components/typeWriter/wh-typeWriter.wxss */ -------------------------------------------------------------------------------- /miniprogram/image/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/cat.png -------------------------------------------------------------------------------- /miniprogram/image/video-image/logo-douyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/video-image/logo-douyin.png -------------------------------------------------------------------------------- /miniprogram/image/video-image/logo-gitShow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/video-image/logo-gitShow.png -------------------------------------------------------------------------------- /miniprogram/image/video-image/logo-microview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/video-image/logo-microview.png -------------------------------------------------------------------------------- /miniprogram/image/video-image/logo-ppx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/video-image/logo-ppx.png -------------------------------------------------------------------------------- /miniprogram/image/video-image/logo-zuiyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/video-image/logo-zuiyou.png -------------------------------------------------------------------------------- /miniprogram/image/wave.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sav7ng/WeHalo/16d78f31cc39f067e5cc72c6a26afeb2cd1e4940/miniprogram/image/wave.gif -------------------------------------------------------------------------------- /miniprogram/pages/friends/friends.js: -------------------------------------------------------------------------------- 1 | const app = getApp(); 2 | const request = require('../../utils/request.js'); 3 | Page({ 4 | 5 | data: { 6 | StatusBar: app.globalData.StatusBar, 7 | CustomBar: app.globalData.CustomBar, 8 | Custom: app.globalData.Custom, 9 | skin: app.globalData.skin, 10 | loading: true, 11 | animationTime: 1, 12 | LinksList: '', 13 | colourList: [{ 14 | colour: 'bg-red' 15 | }, { 16 | colour: 'bg-orange' 17 | }, { 18 | colour: 'bg-yellow' 19 | }, { 20 | colour: 'bg-olive' 21 | }, { 22 | colour: 'bg-green' 23 | }, { 24 | colour: 'bg-cyan' 25 | }, { 26 | colour: 'bg-blue' 27 | }, { 28 | colour: 'bg-purple' 29 | }, { 30 | colour: 'bg-mauve' 31 | }, { 32 | colour: 'bg-pink' 33 | }, { 34 | colour: 'bg-lightBlue' 35 | }], 36 | }, 37 | 38 | onLoad: function (options) { 39 | 40 | this.randomNum(); 41 | var urlLinks = app.globalData.url + '/api/content/links'; 42 | var token = app.globalData.token; 43 | var params = { 44 | sort: 'id,asc' 45 | }; 46 | //@todo Links网络请求API数据 47 | request.requestGetApi(urlLinks, token, params, this, this.successLinks, this.failLinks); 48 | 49 | }, 50 | 51 | onReady: function () { 52 | 53 | }, 54 | 55 | onShow: function () { 56 | 57 | }, 58 | 59 | onHide: function () { 60 | 61 | }, 62 | 63 | onUnload: function () { 64 | 65 | }, 66 | 67 | onPullDownRefresh: function () { 68 | 69 | }, 70 | 71 | onReachBottom: function () { 72 | 73 | }, 74 | 75 | onShareAppMessage: function () { 76 | 77 | }, 78 | 79 | successLinks: function (res, selfObj) { 80 | var that = this; 81 | console.warn(res.data); 82 | that.setData({ 83 | LinksList: res.data, 84 | }); 85 | }, 86 | 87 | failLinks: function (res, selfObj) { 88 | console.error('failLinks', res) 89 | }, 90 | 91 | randomNum: function () { 92 | var num = Math.floor(Math.random() * 10); 93 | this.setData({ 94 | randomNum: num 95 | }); 96 | }, 97 | 98 | prevent(event) { 99 | // console.log(event.currentTarget.dataset.url); 100 | var self = this; 101 | wx.setClipboardData({ 102 | data: event.currentTarget.dataset.url, 103 | }); 104 | 105 | }, 106 | }) -------------------------------------------------------------------------------- /miniprogram/pages/friends/friends.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/friends/friends.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 友情链接 13 | Friends 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {{LinksList.name}} 28 | {{LinksList.description}} 29 | {{LinksList.url}} 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /miniprogram/pages/friends/friends.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/wehalo/wehalo.wxss */ 2 | /* =========== */ 3 | /* 波浪动画 */ 4 | /* =========== */ 5 | @import "../../colorui/animation.wxss"; 6 | 7 | image[class*="gif-"] { 8 | /* border-radius: 6rpx; */ 9 | display: block; 10 | } 11 | 12 | .gif-wave{ 13 | /* position: absolute; */ 14 | width: 100%; 15 | bottom: -2rpx; 16 | left: 0; 17 | z-index: 99; 18 | mix-blend-mode: screen; 19 | height: 100rpx; 20 | } 21 | 22 | page { 23 | background-image: var(--gradualShadow); 24 | width: 100vw; 25 | overflow: hidden; 26 | } 27 | 28 | .DrawerPage { 29 | position: fixed; 30 | width: 100vw; 31 | height: 100vh; 32 | left: 0vw; 33 | background-color: #f1f1f1; 34 | transition: all 0.4s; 35 | } 36 | 37 | .DrawerPage.show { 38 | transform: scale(0.9, 0.9); 39 | left: 85vw; 40 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 41 | transform-origin: 0; 42 | } 43 | 44 | .DrawerPage .cu-bar.tabbar .action button.icon { 45 | width: 64rpx; 46 | height: 64rpx; 47 | line-height: 64rpx; 48 | margin: 0; 49 | display: inline-block; 50 | } 51 | 52 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 53 | margin: 0; 54 | } 55 | 56 | .DrawerPage .nav { 57 | flex: 1; 58 | } 59 | 60 | .DrawerPage .nav .cu-item.cur { 61 | border-bottom: 0; 62 | position: relative; 63 | } 64 | 65 | .DrawerPage .nav .cu-item.cur::after { 66 | content: ""; 67 | width: 10rpx; 68 | height: 10rpx; 69 | background-color: currentColor; 70 | position: absolute; 71 | bottom: 10rpx; 72 | border-radius: 10rpx; 73 | left: 0; 74 | right: 0; 75 | margin: auto; 76 | } 77 | 78 | .DrawerPage .cu-bar.tabbar .action { 79 | flex: initial; 80 | } 81 | 82 | .cu-time { 83 | padding-left:20rpx !important; 84 | } 85 | 86 | 87 | /** 88 | * Friends 样式 89 | **/ 90 | .FriendsRound { 91 | border-radius: 20rpx; 92 | } -------------------------------------------------------------------------------- /miniprogram/pages/halo/halo.js: -------------------------------------------------------------------------------- 1 | // miniprogram/pages/halo/halo.js 2 | const app = getApp(); 3 | const request = require('../../utils/request.js'); 4 | let util = require('../../utils/util.js'); 5 | let delay; 6 | let i = 0; 7 | Page({ 8 | 9 | data: { 10 | adminOpenid: app.globalData.adminOpenid, 11 | roleFlag: app.globalData.roleFlag, 12 | replyValue: null, 13 | commentList: [], 14 | }, 15 | 16 | onLoad: function (options) { 17 | var urlCounts = app.globalData.url + '/api/admin/statistics'; 18 | var paramCounts = {}; 19 | request.requestGetApi(urlCounts, app.globalData.adminToken, paramCounts, this, this.successCounts, this.failCounts); 20 | var urlLatestComments = app.globalData.url + '/api/admin/posts/comments/latest'; 21 | var paramLatestComments = { 22 | top: 5, 23 | }; 24 | request.requestGetApi(urlLatestComments, app.globalData.adminToken, paramLatestComments, this, this.successLatestComments, this.failLatestComments); 25 | 26 | console.warn(app.globalData.userInfo); 27 | 28 | this.numDH(); 29 | }, 30 | 31 | onReady: function () { 32 | }, 33 | 34 | onShow: function () { 35 | this.setData({ 36 | roleFlag: app.globalData.roleFlag, 37 | adminOpenid: app.globalData.adminOpenid, 38 | }) 39 | var that = this; 40 | wx.cloud.callFunction({ 41 | name: 'get_wx_context', 42 | data: { 43 | }, 44 | success(res) { 45 | that.setData({ 46 | openid: res.result.openid 47 | }); 48 | if (res.result.openid == that.data.adminOpenid) { 49 | app.globalData.roleFlag = true; 50 | that.setData({ 51 | roleFlag: true, 52 | }); 53 | } else { 54 | app.globalData.roleFlag = false; 55 | that.setData({ 56 | roleFlag: false, 57 | }); 58 | }; 59 | }, 60 | fail: err => { 61 | }, 62 | }) 63 | }, 64 | 65 | onHide: function () { 66 | }, 67 | 68 | onUnload: function () { 69 | i = 0; 70 | }, 71 | 72 | onPullDownRefresh: function () { 73 | 74 | }, 75 | 76 | onReachBottom: function () { 77 | 78 | }, 79 | 80 | onShareAppMessage: function () { 81 | 82 | }, 83 | numDH: function() { 84 | var that = this; 85 | if(i < 30) { 86 | setTimeout(function () { 87 | that.setData({ 88 | post: i, 89 | comment: i, 90 | visit: i, 91 | day: i, 92 | }) 93 | i++ 94 | that.numDH(); 95 | }, 100) 96 | } else { 97 | that.setData({ 98 | post: that.coutNum(that.data.postCount), 99 | comment: that.coutNum(that.data.commentCount), 100 | visit: that.coutNum(that.data.visitCount), 101 | day: that.coutNum(that.data.birthday), 102 | }) 103 | } 104 | }, 105 | coutNum: function(e) { 106 | if (e > 1000 && e < 10000) { 107 | e = (e / 1000).toFixed(1) + 'k' 108 | } 109 | if (e > 10000) { 110 | e = (e / 10000).toFixed(1) + 'W' 111 | } 112 | return e 113 | }, 114 | 115 | ListTouchStart(e) { 116 | this.setData({ 117 | ListTouchStart: e.touches[0].pageX 118 | }) 119 | }, 120 | 121 | ListTouchMove(e) { 122 | this.setData({ 123 | ListTouchDirection: e.touches[0].pageX - this.data.ListTouchStart > 0 ? 'right' : 'left' 124 | }) 125 | }, 126 | 127 | ListTouchEnd(e) { 128 | if (this.data.ListTouchDirection == 'left') { 129 | this.setData({ 130 | modalName: e.currentTarget.dataset.target 131 | }) 132 | } else { 133 | this.setData({ 134 | modalName: null 135 | }) 136 | } 137 | this.setData({ 138 | ListTouchDirection: null 139 | }) 140 | }, 141 | 142 | showModal(e) { 143 | this.setData({ 144 | modalName: e.currentTarget.dataset.target, 145 | commentid: e.currentTarget.dataset.commentid, 146 | postid: e.currentTarget.dataset.postid, 147 | postTitle: e.currentTarget.dataset.posttitle, 148 | textareaFlag: true, 149 | }) 150 | }, 151 | hideModal(e) { 152 | this.setData({ 153 | modalName: null, 154 | textareaFlag: false, 155 | }) 156 | }, 157 | 158 | textareaAInput(e) { 159 | this.setData({ 160 | textareaAValue: e.detail.value 161 | }) 162 | }, 163 | 164 | replyValue: function(e) { 165 | this.setData({ 166 | replyValue: e.detail.value 167 | }) 168 | console.warn(e.detail.value) 169 | }, 170 | 171 | reply: function() { 172 | 173 | var that = this; 174 | 175 | setTimeout(function () { 176 | if(that.data.replyValue != null && that.data.replyValue != '') { 177 | 178 | that.setData({ 179 | modalName: null, 180 | textareaFlag: false, 181 | }) 182 | 183 | var urlReply = app.globalData.url + '/api/admin/posts/comments'; 184 | var paramReply = { 185 | author: app.globalData.userInfo.nickName, 186 | authorUrl: app.globalData.userInfo.avatarUrl, 187 | content: that.data.replyValue, 188 | email: "853029827@qq.com", 189 | parentId: that.data.commentid, 190 | postId: that.data.postid, 191 | }; 192 | // @todo 后台总览数据网络请求API数据 193 | request.requestPostApi(urlReply, app.globalData.adminToken, paramReply, that, that.successReply, that.failReply); 194 | 195 | console.warn("reply" + that.data.replyValue) 196 | 197 | }else { 198 | wx.showToast({ 199 | title: '内容不能为空', 200 | icon: 'none', 201 | duration: 2000, 202 | mask: true 203 | }) 204 | } 205 | 206 | }, 100) 207 | 208 | 209 | 210 | }, 211 | 212 | successCounts: function(res, selfObj) { 213 | var that = this; 214 | var time1 = Date.parse(new Date()); 215 | var time2 = res.data.birthday; 216 | var runTime = parseInt((time1 - time2) / 1000); 217 | var day = Math.floor(runTime / 86400); 218 | that.setData({ 219 | postCount: res.data.postCount, 220 | commentCount: res.data.commentCount, 221 | visitCount: res.data.visitCount, 222 | birthday: day, 223 | }) 224 | }, 225 | 226 | failCounts: function (res, selfObj) { 227 | console.error('failAdminLogin', res) 228 | }, 229 | 230 | successLatestComments: function(res, selfObj) { 231 | var that = this; 232 | console.warn(res) 233 | var list = res.data; 234 | for (let i = 0; i < list.length; ++i) { 235 | list[i].createTime = util.customFormatTime(list[i].createTime, 'Y-M-D h:m:s'); 236 | if (list[i].isAdmin) { 237 | list[i].email = ''; 238 | list[i].authorUrl = app.globalData.userInfo.avatarUrl; 239 | } 240 | let title=list[i].post.title; 241 | if(title.length>15){ 242 | list[i].post.title=title.substring(0,15)+'...' 243 | } 244 | } 245 | that.setData({ 246 | commentList: res.data, 247 | }) 248 | console.warn(that.data.commentList) 249 | }, 250 | 251 | failLatestComments: function (res, selfObj) { 252 | console.error('failLatestComments', res) 253 | }, 254 | 255 | successReply: function (res, selfObj) { 256 | var that = this; 257 | // console.warn(res); 258 | wx.showToast({ 259 | title: '成功回复评论', 260 | icon: 'none', 261 | duration: 2000, 262 | mask: true 263 | }) 264 | var newComment = [{ 265 | author: res.data.author, 266 | authorUrl: app.globalData.userInfo.avatarUrl, 267 | content: res.data.content, 268 | createTime: util.customFormatTime(res.data.createTime, 'Y-M-D h:m:s'), 269 | email: '', 270 | id: res.data.id, 271 | isAdmin: true, 272 | post: { 273 | id: that.data.postid, 274 | title: that.data.postTitle, 275 | } 276 | }]; 277 | that.setData({ 278 | replyValue: null, 279 | commentList: newComment.concat(that.data.commentList), 280 | }); 281 | }, 282 | 283 | failReply: function (res, selfObj) { 284 | console.error('failReply', res) 285 | }, 286 | 287 | }) -------------------------------------------------------------------------------- /miniprogram/pages/halo/halo.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/halo/halo.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | Dash Board 7 | 8 | 9 | 10 | 11 | 12 | 13 | Halo 仪表盘 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 文章 23 | {{post}} 24 | 25 | 26 | 27 | 28 | 29 | 评论 30 | {{comment}} 31 | 32 | 33 | 34 | 35 | 36 | 访问量 37 | {{visit}} 38 | 39 | 40 | 41 | 42 | 43 | 建立天数 44 | {{day}} 45 | 46 | 47 | 48 | 49 | 50 | 51 | 最新评论 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {{commentList.author}} 63 | 64 | {{commentList.createTime}} 65 | 66 | 67 | 68 | {{commentList.post.title}} 69 | 70 | 71 | {{commentList.content}} 72 | 73 | 74 | 75 | 回复 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 回复 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 取消 99 | 确定 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 您不是管理员无法访问 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /miniprogram/pages/halo/halo.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/halo/halo.wxss */ 2 | /* =========== */ 3 | /* 波浪动画 */ 4 | /* =========== */ 5 | @import "../../colorui/animation.wxss"; 6 | 7 | image[class*="gif-"] { 8 | /* border-radius: 6rpx; */ 9 | display: block; 10 | } 11 | 12 | .gif-wave{ 13 | /* position: absolute; */ 14 | width: 100%; 15 | bottom: -2rpx; 16 | left: 0; 17 | z-index: 99; 18 | mix-blend-mode: screen; 19 | height: 100rpx; 20 | } 21 | 22 | page { 23 | background-image: var(--gradualShadow); 24 | width: 100vw; 25 | overflow: hidden; 26 | } 27 | 28 | .DrawerPage { 29 | position: fixed; 30 | width: 100vw; 31 | height: 100vh; 32 | left: 0vw; 33 | background-color: #f1f1f1; 34 | transition: all 0.4s; 35 | } 36 | 37 | .DrawerPage.show { 38 | transform: scale(0.9, 0.9); 39 | left: 85vw; 40 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 41 | transform-origin: 0; 42 | } 43 | 44 | .DrawerPage .cu-bar.tabbar .action button.icon { 45 | width: 64rpx; 46 | height: 64rpx; 47 | line-height: 64rpx; 48 | margin: 0; 49 | display: inline-block; 50 | } 51 | 52 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 53 | margin: 0; 54 | } 55 | 56 | .DrawerPage .nav { 57 | flex: 1; 58 | } 59 | 60 | .DrawerPage .nav .cu-item.cur { 61 | border-bottom: 0; 62 | position: relative; 63 | } 64 | 65 | .DrawerPage .nav .cu-item.cur::after { 66 | content: ""; 67 | width: 10rpx; 68 | height: 10rpx; 69 | background-color: currentColor; 70 | position: absolute; 71 | bottom: 10rpx; 72 | border-radius: 10rpx; 73 | left: 0; 74 | right: 0; 75 | margin: auto; 76 | } 77 | 78 | .DrawerPage .cu-bar.tabbar .action { 79 | flex: initial; 80 | } 81 | 82 | .cu-time { 83 | padding-left:20rpx !important; 84 | } 85 | 86 | 87 | 88 | .title { 89 | text-align: left; 90 | font-size: 24rpx; 91 | margin-bottom:16rpx; 92 | } 93 | 94 | .bg-image { 95 | background-image: url(https://image.weilanwl.com/color2.0/cardBg.png); 96 | background-size: cover; 97 | background-position: center; 98 | z-index: 2; 99 | } -------------------------------------------------------------------------------- /miniprogram/pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | const app = getApp() 4 | const jinrishici = require('../../utils/jinrishici.js') 5 | const request = require('../../utils/request.js'); 6 | let util = require('../../utils/util.js'); 7 | let touchDotX = 0;//X按下时坐标 8 | let touchDotY = 0;//y按下时坐标 9 | let interval;//计时器 10 | let time = 0;//从按下到松开共多少时间*100 11 | 12 | Page({ 13 | data: { 14 | StatusBar: app.globalData.StatusBar, 15 | CustomBar: app.globalData.CustomBar, 16 | Custom: app.globalData.Custom, 17 | BlogName: app.globalData.BlogName, 18 | HaloUser: app.globalData.HaloUser, 19 | HaloPassword: app.globalData.HaloPassword, 20 | miniProgram: app.globalData.miniProgram, 21 | hasUserInfo: false, 22 | canIUse: wx.canIUse('button.open-type.getUserInfo'), 23 | userInfo: {}, 24 | cardIdex: 1, 25 | randomNum: 0, 26 | animationTime: 1, 27 | moreFlag: false, 28 | pages: 0, 29 | cardCur: 0, 30 | TabCur: 0, 31 | scrollLeft: 0, 32 | openid: '', 33 | Role: '游客', 34 | roleFlag: false, 35 | adminOpenid: app.globalData.adminOpenid, 36 | colourList: [{ 37 | colour: 'bg-red' 38 | }, { 39 | colour: 'bg-orange' 40 | }, { 41 | colour: 'bg-yellow' 42 | }, { 43 | colour: 'bg-olive' 44 | }, { 45 | colour: 'bg-green' 46 | }, { 47 | colour: 'bg-cyan' 48 | }, { 49 | colour: 'bg-blue' 50 | }, { 51 | colour: 'bg-purple' 52 | }, { 53 | colour: 'bg-mauve' 54 | }, { 55 | colour: 'bg-pink' 56 | }, { 57 | colour: 'bg-lightBlue' 58 | }], 59 | categories : [{name:"全部",slug:"all"}], 60 | isPasswordShow : false, 61 | password : null, 62 | secretUrl : null, 63 | }, 64 | /** 65 | * 监听屏幕滚动 判断上下滚动 66 | */ 67 | onPageScroll: function (event) { 68 | this.setData({ 69 | scrollTop: event.detail.scrollTop 70 | }) 71 | }, 72 | //事件处理函数 73 | bindViewTap: function() { 74 | wx.navigateTo({ 75 | url: '../logs/logs' 76 | }) 77 | }, 78 | 79 | /** 80 | * 生命周期函数--监听页面显示 81 | */ 82 | onShow: function () { 83 | var userInfo = wx.getStorageSync('userInfo') 84 | if (userInfo) { 85 | this.setData({ 86 | userInfo: userInfo, 87 | hasUserInfo: true 88 | }) 89 | this.getPermissions() 90 | } 91 | }, 92 | 93 | onLoad: function () { 94 | // 在页面中定义插屏广告 95 | let interstitialAd = null 96 | // 在页面onLoad回调事件中创建插屏广告实例 97 | if (wx.createInterstitialAd) { 98 | interstitialAd = wx.createInterstitialAd({ 99 | adUnitId: 'adunit-f117e72a7c599593' 100 | }) 101 | interstitialAd.onLoad(() => { }) 102 | interstitialAd.onError((err) => { }) 103 | interstitialAd.onClose(() => { }) 104 | } 105 | // 在适合的场景显示插屏广告 106 | if (interstitialAd) { 107 | interstitialAd.show().catch((err) => { 108 | console.error(err) 109 | }) 110 | } 111 | // 每日诗词 112 | jinrishici.load(result => { 113 | // 下面是处理逻辑示例 114 | this.setData({ 115 | jinrishici: result.data.content 116 | }); 117 | }); 118 | var urlPostList = app.globalData.url + '/api/content/posts'; 119 | var token = app.globalData.token; 120 | var params = { 121 | page: 0, 122 | size: 100,//不带参数请求默认10条,又没有查所有文章的接口,所以先暂定100 123 | sort: 'createTime,desc', 124 | }; 125 | var paramBanner = { 126 | page: 0, 127 | size: 5, 128 | sort: 'visits,desc', 129 | }; 130 | // @todo 文章列表网络请求API数据 131 | request.requestGetApi(urlPostList, token, params, this, this.successPostList, this.failPostList); 132 | // @todo 文章Banner网络请求API数据 133 | request.requestGetApi(urlPostList, token, paramBanner, this, this.successBanner, this.failBanner); 134 | var urlAdminLogin = app.globalData.url + '/api/admin/login'; 135 | var paramAdminLogin = { 136 | username: this.data.HaloUser, 137 | password: this.data.HaloPassword 138 | }; 139 | // @todo 获取后台token网络请求API数据 140 | request.requestPostApi(urlAdminLogin, token, paramAdminLogin, this, this.successAdminLogin, this.failAdminLogin); 141 | var that =this; 142 | var urlCategoriesList = app.globalData.url + '/api/content/categories'; 143 | // 查分类 144 | request.requestGetApi(urlCategoriesList, token, {sort:'createTime'}, this, function(res){ 145 | res.data.forEach(element => { 146 | that.data.categories.push(element) 147 | }); 148 | that.setData({ 149 | categories : that.data.categories 150 | }) 151 | }, null); 152 | }, 153 | 154 | getUserProfile: function () { 155 | var that = this; 156 | wx.getUserProfile({ 157 | desc: '用于完善用户资料', 158 | success: (res) => { 159 | if (res.errMsg == "getUserProfile:ok") { 160 | wx.setStorageSync('userInfo',res.userInfo) 161 | app.globalData.userInfo = res.userInfo 162 | that.setData({ 163 | userInfo: res.userInfo, 164 | hasUserInfo: true, 165 | }) 166 | that.getPermissions() 167 | } 168 | } ,fail: err => { 169 | wx.showToast({ 170 | title: '授权后才能体验更多功能哦', 171 | icon: 'none', 172 | duration: 3000 173 | }) 174 | }, 175 | }) 176 | }, 177 | 178 | getPermissions: function () { 179 | var that = this; 180 | wx.cloud.callFunction({ 181 | name: 'get_wx_context', 182 | success(res) { 183 | wx.setStorageSync('openid',res.result.openid) 184 | var role = res.result.openid == that.data.adminOpenid ? '管理员':'游客' 185 | app.globalData.roleFlag = res.result.openid == that.data.adminOpenid; 186 | that.setData({ 187 | Role: role, 188 | roleFlag: res.result.openid == that.data.adminOpenid, 189 | }); 190 | }, 191 | }) 192 | }, 193 | 194 | DotStyle(e) { 195 | this.setData({ 196 | DotStyle: e.detail.value 197 | }) 198 | }, 199 | // cardSwiper 200 | cardSwiper(e) { 201 | this.setData({ 202 | cardCur: e.detail.current 203 | }) 204 | }, 205 | // towerSwiper 206 | // 初始化towerSwiper 207 | towerSwiper(name) { 208 | let list = this.data[name]; 209 | for (let i = 0; i < list.length; i++) { 210 | list[i].zIndex = parseInt(list.length / 2) + 1 - Math.abs(i - parseInt(list.length / 2)) 211 | list[i].mLeft = i - parseInt(list.length / 2) 212 | } 213 | this.setData({ 214 | swiperList: list 215 | }) 216 | }, 217 | // towerSwiper触摸开始 218 | towerStart(e) { 219 | this.setData({ 220 | towerStart: e.touches[0].pageX 221 | }) 222 | }, 223 | // towerSwiper计算方向 224 | towerMove(e) { 225 | this.setData({ 226 | direction: e.touches[0].pageX - this.data.towerStart > 0 ? 'right' : 'left' 227 | }) 228 | }, 229 | // towerSwiper计算滚动 230 | towerEnd(e) { 231 | let direction = this.data.direction; 232 | let list = this.data.swiperList; 233 | if (direction == 'right') { 234 | let mLeft = list[0].mLeft; 235 | let zIndex = list[0].zIndex; 236 | for (let i = 1; i < list.length; i++) { 237 | list[i - 1].mLeft = list[i].mLeft 238 | list[i - 1].zIndex = list[i].zIndex 239 | } 240 | list[list.length - 1].mLeft = mLeft; 241 | list[list.length - 1].zIndex = zIndex; 242 | this.setData({ 243 | swiperList: list 244 | }) 245 | } else { 246 | let mLeft = list[list.length - 1].mLeft; 247 | let zIndex = list[list.length - 1].zIndex; 248 | for (let i = list.length - 1; i > 0; i--) { 249 | list[i].mLeft = list[i - 1].mLeft 250 | list[i].zIndex = list[i - 1].zIndex 251 | } 252 | list[0].mLeft = mLeft; 253 | list[0].zIndex = zIndex; 254 | this.setData({ 255 | swiperList: list 256 | }) 257 | } 258 | }, 259 | showModal(e) { 260 | console.log(e); 261 | this.setData({ 262 | modalName: e.currentTarget.dataset.target 263 | }) 264 | }, 265 | hideModal(e) { 266 | this.setData({ 267 | modalName: null 268 | }) 269 | }, 270 | tabSelect(e) { 271 | this.randomNum(); 272 | this.setData({ 273 | postList: [], 274 | }); 275 | var slug = e.currentTarget.dataset.slug; 276 | var url = slug != 'all'? "/api/content/categories/"+slug+"/posts" : "/api/content/posts"; 277 | var urlPostList = app.globalData.url + url; 278 | var token = app.globalData.token; 279 | var params = { 280 | size: 100, 281 | sort: 'createTime,desc', 282 | password : wx.getStorageSync('password'), 283 | }; 284 | //@todo 文章内容网络请求API数据 285 | request.requestGetApi(urlPostList, token, params, this, this.successPostList, this.failPostList); 286 | this.setData({ 287 | TabCur: e.currentTarget.dataset.id, 288 | scrollLeft: (e.currentTarget.dataset.id - 1) * 60, 289 | secretUrl : slug 290 | }); 291 | }, 292 | 293 | switchSex: function (e) { 294 | // console.warn(e.detail.value); 295 | app.globalData.skin = e.detail.value 296 | console.log(app.globalData.skin) 297 | this.setData({ 298 | skin: e.detail.value 299 | }); 300 | }, 301 | // 触摸开始事件 302 | touchStart: function (e) { 303 | touchDotX = e.touches[0].pageX; // 获取触摸时的原点 304 | touchDotY = e.touches[0].pageY; 305 | // 使用js计时器记录时间 306 | interval = setInterval(function () { 307 | time++; 308 | }, 100); 309 | }, 310 | // 触摸结束事件 311 | touchEnd: function (e) { 312 | let touchMoveX = e.changedTouches[0].pageX; 313 | let touchMoveY = e.changedTouches[0].pageY; 314 | let tmX = touchMoveX - touchDotX; 315 | let tmY = touchMoveY - touchDotY; 316 | if (time < 20) { 317 | let absX = Math.abs(tmX); 318 | let absY = Math.abs(tmY); 319 | if (absX > 2 * absY) { 320 | if (tmX < 0) { 321 | this.setData({ 322 | modalName: null 323 | }) 324 | } else { 325 | this.setData({ 326 | modalName: "viewModal" 327 | }) 328 | } 329 | } 330 | if (absY > absX * 2 && tmY < 0) { 331 | console.log("上滑动=====") 332 | } 333 | } 334 | clearInterval(interval); // 清除setInterval 335 | time = 0; 336 | }, 337 | // 关闭抽屉 338 | shutDownDrawer: function (e) { 339 | this.setData({ 340 | modalName: null 341 | }) 342 | }, 343 | //冒泡事件 344 | maopao: function (e) { 345 | console.log("冒泡...") 346 | }, 347 | showMask: function (e) { 348 | this.selectComponent("#authorCardId").showMask(); 349 | this.shutDownDrawer(); 350 | }, 351 | 352 | //获取随机数 353 | randomNum: function() { 354 | var num = Math.floor(Math.random() * 10); 355 | this.setData({ 356 | randomNum: num 357 | }); 358 | }, 359 | 360 | /** 361 | * 加载更多 362 | */ 363 | loadMore: function () { 364 | 365 | }, 366 | 367 | 368 | 369 | /** 370 | * 文章Banner请求--接口调用成功处理 371 | */ 372 | successBanner: function (res, selfObj) { 373 | var that = this; 374 | var list = res.data.content; 375 | for (let i = 0; i < list.length; ++i) { 376 | list[i].createTime = util.customFormatTime(list[i].createTime, 'Y.M.D'); 377 | } 378 | that.setData({ 379 | bannerPost: res.data.content, 380 | }); 381 | }, 382 | /** 383 | * 文章Banner请求--接口调用失败处理 384 | */ 385 | failBanner: function (res, selfObj) { 386 | console.error('failBanner', res) 387 | }, 388 | 389 | 390 | /** 391 | * 文章列表请求--接口调用成功处理 392 | */ 393 | /** 394 | * 文章列表请求--接口调用成功处理 395 | */ 396 | successPostList: function (res, selfObj) { 397 | var that = this; 398 | if(res.status != 403){ 399 | var list = res.data.content; 400 | for (let i = 0; i < list.length; ++i) { 401 | list[i].createTime = util.customFormatTime(list[i].createTime, 'Y.M.D'); 402 | if (list[i].title.length > 10) { 403 | list[i].title = list[i].title.substring(0, 14) + '...' 404 | } 405 | } 406 | that.setData({ 407 | postList: res.data.content, 408 | moreFlag: res.data.content == "", 409 | pages: res.data.pages, 410 | noPostTitle : "作者会努力更新文章的 . . ." 411 | }); 412 | }else{ 413 | that.setData({ 414 | moreFlag : true, 415 | isPasswordShow : true, 416 | noPostTitle : "该列表为私密列表,请输入访问密码后访问" 417 | }); 418 | wx.showToast({ 419 | title: '请输入正确密码', 420 | icon: 'none', 421 | duration: 2000, 422 | mask: true 423 | }) 424 | } 425 | }, 426 | /** 427 | * 文章列表请求--接口调用失败处理 428 | */ 429 | failPostList: function (res, selfObj) { 430 | console.error('failPostList', res) 431 | }, 432 | 433 | /** 434 | * 后台登入请求--接口调用成功处理 435 | */ 436 | successAdminLogin: function (res, selfObj) { 437 | var that = this; 438 | // that.setData({ 439 | // access_token: res.data.access_token, 440 | // refresh_token: res.data.refresh_token 441 | // }) 442 | app.globalData.adminToken = res.data.access_token; 443 | // clearTimeout(delay); 444 | // console.warn(res) 445 | }, 446 | /** 447 | * 后台登入请求--接口调用失败处理 448 | */ 449 | failAdminLogin: function (res, selfObj) { 450 | console.error('failAdminLogin', res) 451 | }, 452 | 453 | /** 454 | * 搜索文章模块 455 | */ 456 | Search: function(e) { 457 | var content = e.detail.value.replace(/\s+/g, ''); 458 | // console.log(content); 459 | var that = this; 460 | that.setData({ 461 | SearchContent: content, 462 | }); 463 | }, 464 | SearchSubmit: function (e) { 465 | // console.warn(this.data.SearchContent); 466 | 467 | var that = this; 468 | that.setData({ 469 | postList: null, 470 | }); 471 | 472 | var urlPostList = app.globalData.url + '/api/content/posts/search?sort=createTime%2Cdesc&keyword=' + this.data.SearchContent; 473 | var token = app.globalData.token; 474 | var params = {}; 475 | 476 | 477 | //@todo 搜索文章网络请求API数据 478 | request.requestPostApi(urlPostList, token, params, this, this.successSearch, this.failSearch); 479 | }, 480 | successSearch: function (res, selfObj) { 481 | var that = this; 482 | // console.warn(res.data.content); 483 | var list = res.data.content; 484 | for (let i = 0; i < list.length; ++i) { 485 | list[i].createTime = util.customFormatTime(list[i].createTime, 'Y.M.D'); 486 | } 487 | if (res.data.content != "") { 488 | that.setData({ 489 | postList: res.data.content, 490 | moreFlag: false, 491 | pages: res.data.pages, 492 | }); 493 | } else { 494 | that.setData({ 495 | postList: res.data.content, 496 | moreFlag: true, 497 | pages: res.data.pages, 498 | }); 499 | } 500 | }, 501 | failSearch: function (res, selfObj) { 502 | console.error('failSearch', res) 503 | }, 504 | 505 | /** 506 | * 用户点击右上角分享 507 | */ 508 | onShareAppMessage: function () { 509 | return { 510 | title: this.data.jinrishici, 511 | path: '/pages/index/index', 512 | imageUrl: 'https://image.aquan.run/poster.jpg', 513 | } 514 | }, 515 | hidePasswordModal(e) { 516 | this.setData({ 517 | isPasswordShow: false 518 | }) 519 | }, 520 | clickPassword (e){ 521 | 522 | this.setData({ 523 | isPasswordShow: false 524 | }) 525 | wx.setStorageSync('password',this.data.password) 526 | this.randomNum(); 527 | this.setData({ 528 | postList: [], 529 | }); 530 | var urlPostList = app.globalData.url + "/api/content/categories/"+this.data.secretUrl+"/posts"; 531 | var token = app.globalData.token; 532 | var params = { 533 | size: 100, 534 | sort: 'createTime,desc', 535 | password : wx.getStorageSync('password') 536 | }; 537 | //@todo 文章内容网络请求API数据 538 | request.requestGetApi(urlPostList, token, params, this, this.successPostList, this.failPostList); 539 | this.setData({ 540 | TabCur: e.currentTarget.dataset.id, 541 | scrollLeft: (e.currentTarget.dataset.id - 1) * 60 542 | }); 543 | }, 544 | inputPassword(e){ 545 | this.setData({ 546 | password: e.detail.value 547 | }) 548 | } 549 | 550 | }) 551 | 552 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | {{BlogName}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{BlogName}} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {{bannerPost.title}} 34 | 35 | 36 | 37 | 38 | {{bannerPost.createTime}} 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {{item.name}} 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | {{postList.title}} 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | {{postList.title}} 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 109 | 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 确认 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 允许微信授权后,可体验更多功能 139 | 140 | 141 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | {{userInfo.nickName}} 154 | 155 | 156 | {{Role}} 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | GitHub 166 | 167 | 168 | 169 | 173 | 174 | 175 | 176 | 177 | 您不是管理员,无法访问 178 | 179 | 180 | 181 | 182 | 183 | 184 | Halo 仪表盘 185 | 186 | 187 | 188 | 189 | 190 | 191 | WeHalo 192 | 193 | 194 | 195 | 196 | 197 | 炫图模式 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | TalkShow 207 | 208 | 209 | 210 | 211 | 212 | Friends 213 | 214 | 215 | 216 | 220 | 221 | 222 | 223 | 224 | 图库 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | {{ miniProgram.envVersion }} Version 233 | {{ miniProgram.version }} 234 | 235 | 236 | Powered by 237 | WeHalo 238 | 239 | 240 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | .carousel-img { 2 | height: 380rpx; 3 | width: 95%; 4 | /* margin: 20rpx; */ 5 | } 6 | 7 | /* =========== */ 8 | /* Home键 */ 9 | /* =========== */ 10 | 11 | @keyframes scaleDraw { 12 | 0% { 13 | transform: scale(1); 14 | } 15 | 25% { 16 | transform: scale(1.3); 17 | } 18 | 50% { 19 | transform: scale(1); 20 | } 21 | 75% { 22 | transform: scale(1.3); 23 | } 24 | } 25 | 26 | .home { 27 | /* -webkit-animation: scaleDraw 5s ease-in-out infinite; */ 28 | position: fixed; 29 | left: 5%; 30 | top: 4%; 31 | z-index: 10000; 32 | } 33 | 34 | .home-btn { 35 | width: 60rpx !important; 36 | height: 60rpx !important; 37 | } 38 | 39 | 40 | 41 | /* =========== */ 42 | /* 全屏抽屉 */ 43 | /* =========== */ 44 | 45 | page { 46 | background-image: var(--gradualShadow); 47 | width: 100vw; 48 | overflow: hidden; 49 | } 50 | 51 | .DrawerPage { 52 | position: fixed; 53 | width: 100vw; 54 | height: 100vh; 55 | left: 0vw; 56 | background-color: #f1f1f1; 57 | transition: all 0.4s; 58 | overflow-y: auto; 59 | } 60 | 61 | .DrawerPage.show { 62 | transform: scale(0.9, 0.9); 63 | left: 85vw; 64 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 65 | transform-origin: 0; 66 | } 67 | 68 | .DrawerWindow { 69 | position: absolute; 70 | width: 85vw; 71 | height: 100vh; 72 | left: 0; 73 | top: 0; 74 | transform: scale(0.9, 0.9) translateX(-100%); 75 | opacity: 0; 76 | pointer-events: none; 77 | transition: all 0.4s; 78 | } 79 | 80 | .DrawerWindow.show { 81 | transform: scale(1, 1) translateX(0%); 82 | opacity: 1; 83 | pointer-events: all; 84 | } 85 | 86 | .DrawerClose { 87 | position: absolute; 88 | width: 40vw; 89 | height: 100vh; 90 | right: 0; 91 | top: 0; 92 | color: transparent; 93 | padding-bottom: 30rpx; 94 | display: flex; 95 | align-items: flex-end; 96 | justify-content: center; 97 | background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 0.6)); 98 | letter-spacing: 5px; 99 | font-size: 50rpx; 100 | opacity: 0; 101 | pointer-events: none; 102 | transition: all 0.4s; 103 | } 104 | 105 | .DrawerClose.show { 106 | opacity: 1; 107 | pointer-events: all; 108 | width: 15vw; 109 | color: #fff; 110 | } 111 | 112 | .DrawerPage .cu-bar.tabbar .action button.icon { 113 | width: 64rpx; 114 | height: 64rpx; 115 | line-height: 64rpx; 116 | margin: 0; 117 | display: inline-block; 118 | } 119 | 120 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 121 | margin: 0; 122 | } 123 | 124 | .DrawerPage .nav { 125 | flex: 1; 126 | } 127 | 128 | .DrawerPage .nav .cu-item.cur { 129 | border-bottom: 0; 130 | position: relative; 131 | } 132 | 133 | .DrawerPage .nav .cu-item.cur::after { 134 | content: ""; 135 | width: 10rpx; 136 | height: 10rpx; 137 | background-color: currentColor; 138 | position: absolute; 139 | bottom: 10rpx; 140 | border-radius: 10rpx; 141 | left: 0; 142 | right: 0; 143 | margin: auto; 144 | } 145 | 146 | .DrawerPage .cu-bar.tabbar .action { 147 | flex: initial; 148 | } 149 | 150 | .menu-img { 151 | display:inline-block; 152 | margin-right:10rpx; 153 | width:1.6em; 154 | text-align:center; 155 | } 156 | 157 | .mdl-layout__title { 158 | display: block; 159 | position: relative; 160 | font-family: "Roboto","Helvetica","Arial",sans-serif; 161 | font-size: 20px; 162 | line-height: 1; 163 | letter-spacing: .02em; 164 | font-weight: 400; 165 | box-sizing: border-box; 166 | } 167 | 168 | 169 | 170 | /* =========== */ 171 | /* 波浪动画 */ 172 | /* =========== */ 173 | @import "../../colorui/animation.wxss"; 174 | 175 | image[class*="gif-"] { 176 | /* border-radius: 6rpx; */ 177 | display: block; 178 | } 179 | 180 | .gif-wave{ 181 | /* position: absolute; */ 182 | width: 100%; 183 | bottom: -2rpx; 184 | left: 0; 185 | z-index: 99; 186 | mix-blend-mode: screen; 187 | height: 100rpx; 188 | } 189 | 190 | .fall-container { 191 | width: 100%; 192 | display: flex; 193 | } 194 | 195 | .fall-left { 196 | display: flex; 197 | flex-direction: column; 198 | } 199 | 200 | .fall-right { 201 | display: flex; 202 | flex-direction: column; 203 | } 204 | 205 | .list { 206 | position:fixed; 207 | bottom:5%; 208 | left:85%; 209 | } -------------------------------------------------------------------------------- /miniprogram/pages/journal/journal.js: -------------------------------------------------------------------------------- 1 | // miniprogram/pages/journal/journal.js 2 | //获取应用实例 3 | const app = getApp(); 4 | const request = require('../../utils/request.js'); 5 | const util = require('../../utils/util.js'); 6 | Page({ 7 | 8 | /** 9 | * 页面的初始数据 10 | */ 11 | data: { 12 | StatusBar: app.globalData.StatusBar, 13 | CustomBar: app.globalData.CustomBar, 14 | Custom: app.globalData.Custom, 15 | skin: app.globalData.skin, 16 | loading: true, 17 | }, 18 | 19 | /** 20 | * 生命周期函数--监听页面加载 21 | */ 22 | onLoad: function (options) { 23 | var urlContent = app.globalData.url + '/api/content/journals'; 24 | var token = app.globalData.token; 25 | var params = {}; 26 | //@todo 日志内容网络请求API数据 27 | request.requestGetApi(urlContent, token, params, this, this.successJourPost, this.failJourPost); 28 | }, 29 | 30 | /** 31 | * 成功获取日志内容的返回函数 32 | */ 33 | successJourPost: function (res, selfObj) { 34 | var that = this; 35 | for (let i = 0; i < res.data.content.length; i++) { 36 | // 获取随机颜色 37 | let color = this.getRandomColor(); 38 | res.data.content[i].textColor = "text-" + color; 39 | res.data.content[i].bgColor = "bg-" + color; 40 | // 将timestamp转换成年月日的形式 41 | res.data.content[i].createTime = util.customFormatTime(res.data.content[i].createTime, "Y.M.D"); 42 | if (i > 0 && res.data.content[i].createTime === res.data.content[i - 1].createTime) { 43 | // 标志位,给html判断可以有时间title 的 44 | res.data.content[i].hasTime = false; 45 | } 46 | else res.data.content[i].hasTime = true; 47 | } 48 | 49 | that.setData({ 50 | jourContent: res.data.content, 51 | }) 52 | }, 53 | 54 | /** 55 | * 获取日志失败的处理函数 56 | */ 57 | failJourPost: function (res, selfObj) { 58 | console.error('failJourPost', res); 59 | }, 60 | 61 | /** 62 | * @return: 颜色的字符串。例如:red;green;pink等 63 | */ 64 | getRandomColor: function () { 65 | var colors = ["pink", "orange", "green", "red", "blue", "mauve", "purple", "olive"]; 66 | return colors[Math.floor(Math.random() * colors.length)]; 67 | } 68 | 69 | }) -------------------------------------------------------------------------------- /miniprogram/pages/journal/journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/journal/journal.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 返回 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TalkShow 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |   24 | 25 | 26 | 27 | 28 | {{jourContent.createTime}} 29 | 30 | 31 | 32 | {{jourContent.sourceContent}} 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Powered by 41 | WeHalo 42 | 43 | 44 | -------------------------------------------------------------------------------- /miniprogram/pages/journal/journal.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/journal/journal.wxss */ 2 | /* =========== */ 3 | /* 波浪动画 */ 4 | /* =========== */ 5 | @import "../../colorui/animation.wxss"; 6 | 7 | image[class*="gif-"] { 8 | /* border-radius: 6rpx; */ 9 | display: block; 10 | } 11 | 12 | .gif-wave{ 13 | /* position: absolute; */ 14 | width: 100%; 15 | bottom: -2rpx; 16 | left: 0; 17 | z-index: 99; 18 | mix-blend-mode: screen; 19 | height: 100rpx; 20 | } 21 | 22 | page { 23 | background-image: var(--gradualShadow); 24 | width: 100vw; 25 | overflow: hidden; 26 | } 27 | 28 | .DrawerPage { 29 | position: fixed; 30 | width: 100vw; 31 | height: 100vh; 32 | left: 0vw; 33 | background-color: #f1f1f1; 34 | transition: all 0.4s; 35 | } 36 | 37 | .DrawerPage.show { 38 | transform: scale(0.9, 0.9); 39 | left: 85vw; 40 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 41 | transform-origin: 0; 42 | } 43 | 44 | .DrawerPage .cu-bar.tabbar .action button.icon { 45 | width: 64rpx; 46 | height: 64rpx; 47 | line-height: 64rpx; 48 | margin: 0; 49 | display: inline-block; 50 | } 51 | 52 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 53 | margin: 0; 54 | } 55 | 56 | .DrawerPage .nav { 57 | flex: 1; 58 | } 59 | 60 | .DrawerPage .nav .cu-item.cur { 61 | border-bottom: 0; 62 | position: relative; 63 | } 64 | 65 | .DrawerPage .nav .cu-item.cur::after { 66 | content: ""; 67 | width: 10rpx; 68 | height: 10rpx; 69 | background-color: currentColor; 70 | position: absolute; 71 | bottom: 10rpx; 72 | border-radius: 10rpx; 73 | left: 0; 74 | right: 0; 75 | margin: auto; 76 | } 77 | 78 | .DrawerPage .cu-bar.tabbar .action { 79 | flex: initial; 80 | } 81 | 82 | .cu-time { 83 | padding-left:20rpx !important; 84 | } -------------------------------------------------------------------------------- /miniprogram/pages/photos/photos.js: -------------------------------------------------------------------------------- 1 | const app = getApp() 2 | const request = require('../../utils/request.js'); 3 | Page({ 4 | 5 | /** 6 | * 页面的初始数据 7 | */ 8 | data: { 9 | items: [], 10 | selected: '', 11 | basicsList: [{ 12 | icon: 'radioboxfill', 13 | name: '下载中' 14 | }, { 15 | icon: 'roundcheckfill', 16 | name: '下载完成' 17 | }, ], 18 | basics: 0, 19 | isDownload: false, 20 | TabCur: 0, 21 | scrollLeft: 0, 22 | Tab: ['全部'], 23 | isCard: false, 24 | roleFlag: false, 25 | isImageShow: false, 26 | grouping: '', 27 | customGrouping: '', 28 | isUpload: false, 29 | isImageIcon: false 30 | }, 31 | 32 | /** 33 | * 生命周期函数--监听页面加载 34 | */ 35 | onLoad: function (options) { 36 | //管理员才能上传 37 | if (app.globalData.adminOpenid == wx.getStorageSync('openid')) { 38 | this.setData({ 39 | isImageIcon: true 40 | }) 41 | } 42 | this.imageInit() 43 | }, 44 | imageInit() { 45 | let that = this; 46 | var url = app.globalData.url + '/api/content/photos/latest'; 47 | request.requestGetApi(url, app.globalData.token, null, this, function (res) { 48 | let i = 1; 49 | res.data.forEach(element => { 50 | if (that.data.Tab.indexOf(element.team) == -1 && "" != element.team) { 51 | var tab = 'Tab[' + i++ + ']'; 52 | that.setData({ 53 | [tab]: element.team 54 | }); 55 | } 56 | }); 57 | that.setData({ 58 | roleFlag: app.globalData.roleFlag, 59 | items: res.data 60 | }) 61 | }, 62 | function (res) { 63 | console.error(res) 64 | }); 65 | }, 66 | onlongclick: function (e) { 67 | this.setData({ 68 | isShow: true, 69 | selected: e.currentTarget.dataset.url, 70 | isDownload: false 71 | }) 72 | }, 73 | hideModal() { 74 | this.setData({ 75 | isShow: false 76 | }) 77 | }, 78 | saveImage() { 79 | let that = this 80 | that.setData({ 81 | isDownload: true, 82 | basics: 0 83 | }) 84 | wx.getImageInfo({ 85 | src: that.data.selected, 86 | success: function (res) { 87 | var path = res.path; 88 | wx.saveImageToPhotosAlbum({ 89 | filePath: path, 90 | success: function (res) { 91 | that.setData({ 92 | basics: 1 93 | }) 94 | }, 95 | fail: function (res) {} 96 | }) 97 | } 98 | }); 99 | }, 100 | tabSelect(e) { 101 | let that = this; 102 | let team = e.currentTarget.dataset.item; 103 | var url = app.globalData.url + '/api/content/photos/latest'; 104 | var params = null; 105 | if (team != '全部') { 106 | url = app.globalData.url + '/api/content/photos'; 107 | params = { 108 | team: team 109 | }; 110 | } 111 | request.requestGetApi(url, app.globalData.token, params, this, function (res) { 112 | let data = res.data.content 113 | if (team == '全部') { 114 | data = res.data 115 | } 116 | that.setData({ 117 | items: data, 118 | TabCur: e.currentTarget.dataset.id, 119 | scrollLeft: (e.currentTarget.dataset.id - 1) * 60 120 | }) 121 | }, 122 | function (res) { 123 | console.error(res) 124 | }); 125 | }, 126 | ChooseImage() { 127 | var that = this 128 | wx.chooseImage({ 129 | count: 9, 130 | sizeType: ['original'], 131 | sourceType: ['album', 'camera'], 132 | success: (res) => { 133 | var imgNum = res.tempFilePaths.length; //图片数量 134 | var i = 1; 135 | that.setData({ 136 | isUpload: true 137 | }) 138 | res.tempFilePaths.forEach(element => { 139 | wx.uploadFile({ 140 | url: app.globalData.url+'/api/admin/attachments/upload', 141 | filePath: element, 142 | name: 'file', 143 | header: { 144 | 'content-type': 'multipart/form-data', 145 | 'ADMIN-Authorization': app.globalData.adminToken, 146 | 'API-Authorization': app.globalData.adminToken, 147 | }, 148 | success: function (res) { 149 | var imageData = JSON.parse(res.data) 150 | var urlCounts = app.globalData.url + '/api/admin/photos'; 151 | var paramCounts = { 152 | name: imageData.data.name, 153 | team: that.data.grouping, 154 | thumbnail: imageData.data.path, 155 | url: imageData.data.path, 156 | }; 157 | request.requestPostApi(urlCounts, app.globalData.adminToken, paramCounts, this, function (res) { 158 | if (imgNum == i++) { 159 | that.imageInit() 160 | that.setData({ 161 | isUpload: false, 162 | isImageShow: false 163 | }) 164 | } 165 | }, function (res) { 166 | console.error(res) 167 | }); 168 | }, 169 | fail: function (res) { 170 | console.error(res) 171 | } 172 | }) 173 | }); 174 | }, 175 | fail: (res) => { 176 | console.error(res) 177 | } 178 | }); 179 | }, 180 | isCard(e) { 181 | this.setData({ 182 | isCard: e.detail.value 183 | }) 184 | }, 185 | imageShow(e) { 186 | this.setData({ 187 | isImageShow: true 188 | }) 189 | }, 190 | checkedGroup(e) { 191 | this.setData({ 192 | grouping: e.currentTarget.dataset.group 193 | }) 194 | }, 195 | groudBindblur(e) { 196 | this.setData({ 197 | customGrouping: e.detail.value 198 | }) 199 | }, 200 | hideImageModal(e) { 201 | this.setData({ 202 | isImageShow: false 203 | }) 204 | } 205 | }) -------------------------------------------------------------------------------- /miniprogram/pages/photos/photos.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/photos/photos.wxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 返回 6 | 7 | 图库 8 | 9 | 10 | 11 | 12 | 14 | {{item}} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 精简排列 22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 61 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 图片上传 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 图片上传中 97 | 98 | -------------------------------------------------------------------------------- /miniprogram/pages/photos/photos.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/photos.wxss */ 2 | @import "../../colorui/animation.wxss"; 3 | .add { 4 | position:fixed; 5 | bottom:5%; 6 | left:80%; 7 | } -------------------------------------------------------------------------------- /miniprogram/pages/post/post.js: -------------------------------------------------------------------------------- 1 | // miniprogram/pages/post/post.js 2 | const app = getApp(); 3 | const request = require('../../utils/request.js'); 4 | let time = require('../../utils/util.js'); 5 | var countdown = 60; 6 | 7 | Page({ 8 | 9 | /** 10 | * 页面的初始数据 11 | */ 12 | data: { 13 | StatusBar: app.globalData.StatusBar, 14 | CustomBar: app.globalData.CustomBar, 15 | Custom: app.globalData.Custom, 16 | skin: app.globalData.skin, 17 | style: app.globalData.highlightStyle, 18 | hasUserInfo: false, 19 | canIUse: wx.canIUse('button.open-type.getUserInfo'), 20 | CommentShow: false, 21 | ButtonTimer: '',// 按钮定时器 22 | LastTime: 60, 23 | CommentSwitch: true, 24 | commentValue:'' 25 | }, 26 | 27 | /** 28 | * 生命周期函数--监听页面加载 29 | */ 30 | onLoad: function (options) { 31 | 32 | 33 | 34 | // 在页面中定义插屏广告 35 | let interstitialAd = null 36 | 37 | // 在页面onLoad回调事件中创建插屏广告实例 38 | if (wx.createInterstitialAd) { 39 | interstitialAd = wx.createInterstitialAd({ 40 | adUnitId: 'adunit-296c920c08da636d' 41 | }) 42 | interstitialAd.onLoad(() => { }) 43 | interstitialAd.onError((err) => { }) 44 | interstitialAd.onClose(() => { }) 45 | } 46 | 47 | // 在适合的场景显示插屏广告 48 | if (interstitialAd) { 49 | interstitialAd.show().catch((err) => { 50 | console.error(err) 51 | }) 52 | } 53 | 54 | 55 | var postId = options.postId; 56 | // console.log(postId); 57 | this.setData({ 58 | postId: postId 59 | }) 60 | 61 | 62 | var urlContent = app.globalData.url + '/api/content/posts/' + postId; 63 | var token = app.globalData.token; 64 | var params = {}; 65 | //@todo 文章内容网络请求API数据 66 | request.requestGetApi(urlContent, token, params, this, this.successFunPost, this.failFunPost); 67 | 68 | var urlComments = urlContent + '/comments/list_view'; 69 | //@todo 评论列表网络请求API数据 70 | request.requestGetApi(urlComments, token, params, this, this.successComment, this.failComment); 71 | var urlSwitch = app.globalData.url + '/api/content/options/keys/comment_api_enabled'; 72 | //@todo 评论开启按钮网络请求API数据 73 | request.requestGetApi(urlSwitch, token, params, this, this.successSwitch, this.failSwitch); 74 | 75 | 76 | }, 77 | 78 | /** 79 | * 生命周期函数--监听页面初次渲染完成 80 | */ 81 | onReady: function () { 82 | 83 | }, 84 | 85 | /** 86 | * 生命周期函数--监听页面显示 87 | */ 88 | onShow: function () { 89 | 90 | // console.warn(app.globalData.userInfo); 91 | var userInfo = wx.getStorageSync('userInfo') 92 | if (userInfo) { 93 | this.setData({ 94 | userInfo: userInfo, 95 | hasUserInfo: true 96 | }) 97 | } else if (this.data.canIUse) { 98 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 99 | // 所以此处加入 callback 以防止这种情况 100 | app.userInfoReadyCallback = res => { 101 | this.setData({ 102 | userInfo: res.userInfo, 103 | hasUserInfo: true, 104 | }) 105 | } 106 | } 107 | }, 108 | 109 | /** 110 | * 生命周期函数--监听页面隐藏 111 | */ 112 | onHide: function () { 113 | 114 | }, 115 | 116 | /** 117 | * 生命周期函数--监听页面卸载 118 | */ 119 | onUnload: function () { 120 | 121 | }, 122 | 123 | /** 124 | * 页面相关事件处理函数--监听用户下拉动作 125 | */ 126 | onPullDownRefresh: function () { 127 | 128 | }, 129 | 130 | /** 131 | * 页面上拉触底事件的处理函数 132 | */ 133 | onReachBottom: function () { 134 | 135 | }, 136 | 137 | /** 138 | * 用户点击右上角分享 139 | */ 140 | onShareAppMessage: function () { 141 | // console.warn(this.data.postId); 142 | return { 143 | title: this.data.postTitle, 144 | path: '/pages/post/post?postId=' + this.data.postId, 145 | imageUrl: this.data.postThumbnail, 146 | } 147 | }, 148 | 149 | /** 150 | * 用户点击右上角分享 151 | */ 152 | onShareTimeline: function () { 153 | // console.warn(this.data.postId); 154 | return { 155 | title: this.data.postTitle, 156 | path: '/pages/post/post?postId=' + this.data.postId, 157 | imageUrl: this.data.postThumbnail, 158 | } 159 | }, 160 | 161 | getUserProfile: function () { 162 | var that = this 163 | wx.getUserProfile({ 164 | desc: '用于完善用户资料', 165 | success: (res) => { 166 | if (res.errMsg == "getUserProfile:ok") { 167 | wx.setStorageSync('userInfo',res.userInfo) 168 | that.setData({ 169 | userInfo: res.userInfo, 170 | hasUserInfo: true, 171 | }) 172 | } 173 | } ,fail: err => { 174 | wx.showToast({ 175 | title: '授权后才能评论哦', 176 | icon: 'none', 177 | duration: 3000 178 | }) 179 | }, 180 | }) 181 | }, 182 | 183 | /** 184 | * 文章详情请求--接口调用成功处理 185 | */ 186 | successFunPost: function (res, selfObj) { 187 | var that = this; 188 | 189 | // console.warn(res.data); 190 | var createTime = res.data.createTime; 191 | // time.customFormatTime(createTime, 'Y-M-D h:m:s'); 192 | // 当前时间的日期格式 193 | // var date = new Date(); 194 | // console.log(time.formatTime(date+"123")); 195 | 196 | that.setData({ 197 | postTitle: res.data.title, 198 | postVisits: res.data.visits, 199 | postLikes: res.data.likes, 200 | postContent: res.data.originalContent, 201 | postDate: time.customFormatTime(createTime, 'Y-M-D'), 202 | postTags: res.data.tags, 203 | postThumbnail: res.data.thumbnail, 204 | }) 205 | // console.warn(postTags); 206 | 207 | }, 208 | /** 209 | * 文章详情请求--接口调用失败处理 210 | */ 211 | failFunPost: function (res, selfObj) { 212 | console.error('failFunPosts', res) 213 | }, 214 | 215 | 216 | /** 217 | * 评论列表请求--接口调用成功处理 218 | */ 219 | successComment: function (res, selfObj) { 220 | var that = this; 221 | // console.warn(res.data); 222 | var list = res.data.content; 223 | if(list.length != 0){ 224 | for (let i = 0; i < list.length; ++i) { 225 | list[i].createTime = time.customFormatTime(list[i].createTime, 'Y-M-D h:m:s'); 226 | list[i].falg = true; 227 | if (list[i].isAdmin) { 228 | list[i].email = ''; 229 | list[i].authorUrl = 'https://cn.gravatar.com/avatar/3958035fa354403fa9ca3fca36b08068?s=256&d=mm'; 230 | } 231 | } 232 | 233 | list[list.length - 1].falg = false; 234 | } 235 | that.setData({ 236 | commentList: res.data.content, 237 | }) 238 | }, 239 | /** 240 | * 评论列表请求--接口调用失败处理 241 | */ 242 | failComment: function (res, selfObj) { 243 | console.error('failComment', res) 244 | }, 245 | 246 | 247 | 248 | /** 249 | * 评论模块 250 | */ 251 | Comment: function (e) { 252 | var content = e.detail.value.replace(/\s+/g, ''); 253 | // console.log(content); 254 | var that = this; 255 | that.setData({ 256 | CommentContent: content, 257 | }); 258 | }, 259 | 260 | CommentSubmit: function (e) { 261 | 262 | // console.warn(this.userInfo); 263 | var that = this; 264 | 265 | if (!that.data.CommentContent) { 266 | wx.showToast({ 267 | title: '评论内容不能为空!', 268 | icon: 'none', 269 | duration: 2000 270 | }) 271 | // console.error("评论内容为空!"); 272 | } else { 273 | that.setData({ 274 | CommentShow: true, 275 | }); 276 | that.data.ButtonTimer = setInterval(function () { 277 | if (countdown == 0) { 278 | that.setData({ 279 | CommentShow: false, 280 | }) 281 | countdown = 60; 282 | clearInterval(that.data.ButtonTimer); 283 | return; 284 | } else { 285 | that.setData({ 286 | LastTime: countdown 287 | }); 288 | // console.warn(countdown); 289 | countdown--; 290 | } 291 | }, 1000) 292 | // console.warn(that.data.CommentContent); 293 | wx.cloud.callFunction({ 294 | name: 'msg_sec_check', 295 | data: { 296 | content: that.data.CommentContent 297 | } 298 | }).then(ckres => { 299 | if (ckres.result.errCode == 0) { 300 | var urlPostList = app.globalData.url + '/api/content/posts/comments'; 301 | var token = app.globalData.token; 302 | var params = { 303 | author: that.data.userInfo.nickName, 304 | authorUrl: "https://github.com/aquanlerou/WeHalo", 305 | content: that.data.CommentContent, 306 | email: "aquanlerou@eunji.cn", 307 | parentId: 0, 308 | postId: that.data.postId, 309 | }; 310 | //@todo 网络请求API数据 311 | request.requestPostApi(urlPostList, token, params, this, this.successSendComment, this.failSendComment); 312 | } else { 313 | // wx.hideLoading(); 314 | // wx.showModal({ 315 | // title: '提醒', 316 | // content: '请注意言论', 317 | // showCancel: false 318 | // }) 319 | wx.showToast({ 320 | title: '请注意言论!', 321 | icon: 'none', 322 | duration: 2000 323 | }) 324 | that.setData({ 325 | commentValue: "", 326 | CommentContent: undefined 327 | }) 328 | } 329 | }) 330 | } 331 | 332 | 333 | 334 | }, 335 | 336 | CommentSubmitTips: function() { 337 | wx.showToast({ 338 | title: this.data.LastTime + "s 后再次评论", 339 | icon: 'none', 340 | duration: 1000 341 | }) 342 | }, 343 | 344 | Likes: function() { 345 | wx.showToast({ 346 | title: "文章点赞功能开发中...", 347 | icon: 'none', 348 | duration: 2000 349 | }) 350 | }, 351 | 352 | 353 | successSendComment: function (res, selfObj) { 354 | var that = this; 355 | // console.warn(res.data); 356 | that.setData({ 357 | commentValue:"", 358 | CommentContent:undefined 359 | }) 360 | wx.showToast({ 361 | title: '感谢你的评论与支持!', 362 | icon: 'none', 363 | duration: 2000 364 | }) 365 | var token = app.globalData.token; 366 | var urlContent = app.globalData.url + '/api/content/posts/' + that.data.postId; 367 | var urlComments = urlContent + '/comments/list_view'; 368 | var params = {}; 369 | //@todo 评论列表网络请求API数据 370 | request.requestGetApi(urlComments, token, params, this, this.successComment, this.failComment); 371 | }, 372 | 373 | failSendComment: function (res, selfObj) { 374 | console.error('failComment', res) 375 | }, 376 | 377 | /** 378 | * 评论开关按钮回调 379 | */ 380 | successSwitch: function(res, selfObj) { 381 | var that = this; 382 | // console.warn(res.data); 383 | that.setData({ 384 | CommentSwitch: !res.data, 385 | }); 386 | }, 387 | failSwitch: function (res, selfObj) { 388 | console.error('failSwitch', res) 389 | }, 390 | 391 | 392 | }) 393 | -------------------------------------------------------------------------------- /miniprogram/pages/post/post.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "htmltowxml": "plugin://htmltowxml/view" 4 | } 5 | } -------------------------------------------------------------------------------- /miniprogram/pages/post/post.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {{postTitle}} 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | {{postTags.name}} 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {{postLikes}} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {{postVisits}} 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {{postDate}} 57 | 58 | 59 |   60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 评论 74 | 75 | 76 | 77 | 78 | 79 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | {{commentItem.author}} 107 | 108 | {{commentItem.createTime}} 109 | 110 | 111 | 112 | {{commentItem.content}} 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /miniprogram/pages/post/post.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/post/post.wxss */ 2 | /* =========== */ 3 | /* 波浪动画 */ 4 | /* =========== */ 5 | @import "../../colorui/animation.wxss"; 6 | 7 | image[class*="gif-"] { 8 | /* border-radius: 6rpx; */ 9 | display: block; 10 | } 11 | 12 | .gif-wave{ 13 | /* position: absolute; */ 14 | width: 100%; 15 | bottom: -2rpx; 16 | left: 0; 17 | z-index: 99; 18 | mix-blend-mode: screen; 19 | height: 100rpx; 20 | } 21 | 22 | page { 23 | background-image: var(--gradualShadow); 24 | width: 100vw; 25 | overflow: hidden; 26 | } 27 | 28 | .DrawerPage { 29 | position: fixed; 30 | width: 100vw; 31 | height: 100vh; 32 | left: 0vw; 33 | background-color: #f1f1f1; 34 | transition: all 0.4s; 35 | } 36 | 37 | .DrawerPage.show { 38 | transform: scale(0.9, 0.9); 39 | left: 85vw; 40 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 41 | transform-origin: 0; 42 | } 43 | 44 | .DrawerPage .cu-bar.tabbar .action button.icon { 45 | width: 64rpx; 46 | height: 64rpx; 47 | line-height: 64rpx; 48 | margin: 0; 49 | display: inline-block; 50 | } 51 | 52 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 53 | margin: 0; 54 | } 55 | 56 | .DrawerPage .nav { 57 | flex: 1; 58 | } 59 | 60 | .DrawerPage .nav .cu-item.cur { 61 | border-bottom: 0; 62 | position: relative; 63 | } 64 | 65 | .DrawerPage .nav .cu-item.cur::after { 66 | content: ""; 67 | width: 10rpx; 68 | height: 10rpx; 69 | background-color: currentColor; 70 | position: absolute; 71 | bottom: 10rpx; 72 | border-radius: 10rpx; 73 | left: 0; 74 | right: 0; 75 | margin: auto; 76 | } 77 | 78 | .DrawerPage .cu-bar.tabbar .action { 79 | flex: initial; 80 | } 81 | 82 | .cu-time { 83 | padding-left:20rpx !important; 84 | } 85 | 86 | /** 评论栏样式 **/ 87 | .comment { 88 | position: fixed; 89 | bottom: 0; 90 | /* background: url("https://blog.eunji.cn/upload/2018/11/code120181219113843975.png") no-repeat; */ 91 | /* background-size: cover; */ 92 | color: #000; 93 | width: 100%; 94 | height: 90rpx; 95 | z-index: 1050; 96 | background-color: #ffffff; 97 | box-shadow:0px 5px 22px 5px rgb(180, 180, 180); 98 | } 99 | 100 | 101 | /** 广告位样式 **/ 102 | .ad { 103 | margin: 20rpx; 104 | } 105 | -------------------------------------------------------------------------------- /miniprogram/pages/wehalo/wehalo.js: -------------------------------------------------------------------------------- 1 | // miniprogram/pages/wehalo/wehalo.js 2 | //获取应用实例 3 | const app = getApp() 4 | Page({ 5 | 6 | /** 7 | * 页面的初始数据 8 | */ 9 | data: { 10 | StatusBar: app.globalData.StatusBar, 11 | CustomBar: app.globalData.CustomBar, 12 | Custom: app.globalData.Custom, 13 | skin: app.globalData.skin, 14 | loading: true, 15 | }, 16 | 17 | /** 18 | * 生命周期函数--监听页面加载 19 | */ 20 | onLoad: function (options) { 21 | }, 22 | 23 | /** 24 | * 生命周期函数--监听页面初次渲染完成 25 | */ 26 | onReady: function () { 27 | 28 | }, 29 | 30 | /** 31 | * 生命周期函数--监听页面显示 32 | */ 33 | onShow: function () { 34 | 35 | }, 36 | 37 | /** 38 | * 生命周期函数--监听页面隐藏 39 | */ 40 | onHide: function () { 41 | 42 | }, 43 | 44 | /** 45 | * 生命周期函数--监听页面卸载 46 | */ 47 | onUnload: function () { 48 | 49 | }, 50 | 51 | /** 52 | * 页面相关事件处理函数--监听用户下拉动作 53 | */ 54 | onPullDownRefresh: function () { 55 | 56 | }, 57 | 58 | /** 59 | * 页面上拉触底事件的处理函数 60 | */ 61 | onReachBottom: function () { 62 | 63 | }, 64 | 65 | /** 66 | * 用户点击右上角分享 67 | */ 68 | onShareAppMessage: function () { 69 | 70 | }, 71 | 72 | }) -------------------------------------------------------------------------------- /miniprogram/pages/wehalo/wehalo.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /miniprogram/pages/wehalo/wehalo.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 23 | 24 | 25 | 26 | 90% 27 | 10% 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |   37 | 38 | 39 | 40 | 2019.10.10 41 | 42 | 43 | 44 | 2019.09.23 WeHalo支持最新版本Halo 45 | 46 | 47 | 48 | 49 | 50 | 敬请期待 WeHalo 脱胎换骨 ~ 51 | 52 | 53 | WeHalo_Meow... 54 | 55 | 56 | 57 | WeHalo 启动开发新版本支持最新版本 Halo 的 Meow 版本 58 | 59 | 60 | 2019.07.01 61 | 62 | 63 | 64 | 65 | 利用微信云开发实现记录文章浏览数与文章点赞功能 66 | 67 | 68 | 2019.01.30 69 | 70 | 71 | 72 | 添加微信授权后才可评论文章 73 | 74 | 75 | 76 | 77 | 文章弹幕流评论 78 | 79 | 80 | 2019.01.30 81 | 82 | 83 | 84 | 完成对接口进行封装处理 85 | 86 | 87 | 2019.01.08 88 | 89 | 90 | 91 | 自定义导航栏,动画效果 92 | 93 | 94 | 95 | 96 | 生成海报功能 97 | 98 | 99 | 100 | 101 | 开源项目名 wxBlog 更改 WeHalo 102 | 103 | 104 | 2018.12.07 105 | 106 | 107 | 108 | 在GitHub上创建开源项目 wxBlog 109 | 110 | 111 | 2018.11.26 112 | 113 | 114 | 115 | 116 | Powered by 117 | WeHalo 118 | 119 | 120 | -------------------------------------------------------------------------------- /miniprogram/pages/wehalo/wehalo.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/wehalo/wehalo.wxss */ 2 | /* =========== */ 3 | /* 波浪动画 */ 4 | /* =========== */ 5 | @import "../../colorui/animation.wxss"; 6 | 7 | image[class*="gif-"] { 8 | /* border-radius: 6rpx; */ 9 | display: block; 10 | } 11 | 12 | .gif-wave{ 13 | /* position: absolute; */ 14 | width: 100%; 15 | bottom: -2rpx; 16 | left: 0; 17 | z-index: 99; 18 | mix-blend-mode: screen; 19 | height: 100rpx; 20 | } 21 | 22 | page { 23 | background-image: var(--gradualShadow); 24 | width: 100vw; 25 | overflow: hidden; 26 | } 27 | 28 | .DrawerPage { 29 | position: fixed; 30 | width: 100vw; 31 | height: 100vh; 32 | left: 0vw; 33 | background-color: #f1f1f1; 34 | transition: all 0.4s; 35 | } 36 | 37 | .DrawerPage.show { 38 | transform: scale(0.9, 0.9); 39 | left: 85vw; 40 | box-shadow: 0 0 60rpx rgba(0, 0, 0, 0.2); 41 | transform-origin: 0; 42 | } 43 | 44 | .DrawerPage .cu-bar.tabbar .action button.icon { 45 | width: 64rpx; 46 | height: 64rpx; 47 | line-height: 64rpx; 48 | margin: 0; 49 | display: inline-block; 50 | } 51 | 52 | .DrawerPage .cu-bar.tabbar .action .cu-avatar { 53 | margin: 0; 54 | } 55 | 56 | .DrawerPage .nav { 57 | flex: 1; 58 | } 59 | 60 | .DrawerPage .nav .cu-item.cur { 61 | border-bottom: 0; 62 | position: relative; 63 | } 64 | 65 | .DrawerPage .nav .cu-item.cur::after { 66 | content: ""; 67 | width: 10rpx; 68 | height: 10rpx; 69 | background-color: currentColor; 70 | position: absolute; 71 | bottom: 10rpx; 72 | border-radius: 10rpx; 73 | left: 0; 74 | right: 0; 75 | margin: auto; 76 | } 77 | 78 | .DrawerPage .cu-bar.tabbar .action { 79 | flex: initial; 80 | } 81 | 82 | .cu-time { 83 | padding-left:20rpx !important; 84 | } -------------------------------------------------------------------------------- /miniprogram/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /miniprogram/utils/jinrishici.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 今日诗词V2 Mini-Program-SDK 1.0 3 | * https://www.jinrishici.com 4 | */ 5 | let waitingQueue = [] 6 | let lock = false 7 | const load = callback => { 8 | getTokenAndDo(token => { 9 | wx.request({ 10 | url: 'https://v2.jinrishici.com/one.json?client=mini-progrram-sdk/1.0', 11 | header: { 12 | 'X-User-Token': token 13 | }, 14 | success: res => { 15 | if (res.data.status === "success") { 16 | callback(res.data) 17 | } else { 18 | console.error("今日诗词API 获取古诗词 失败,错误原因:" + res.data.errMessage) 19 | } 20 | }, 21 | fail: () => { 22 | console.error("今日诗词-小程序SDK 获取古诗词失败,可能是网络问题或者您没有添加到域名白名单") 23 | } 24 | }) 25 | }) 26 | } 27 | 28 | const getTokenAndDo = callback => { 29 | let token = wx.getStorageSync("jinrishici-token") 30 | if (token) { 31 | callback(token) 32 | } else { 33 | waitingQueue.push(callback) 34 | if (lock) { 35 | return; 36 | } 37 | lock = true 38 | wx.request({ 39 | url: 'https://v2.jinrishici.com/token?client=mini-progrram-sdk/1.0', 40 | success: res => { 41 | if (res.data.status === "success") { 42 | wx.setStorageSync("jinrishici-token", res.data.data) 43 | lock = false 44 | while (waitingQueue.length > 0) { 45 | waitingQueue.pop()(res.data.data) 46 | } 47 | } else { 48 | console.error("今日诗词API获取 Token 失败,错误原因:" + res.data.errMessage) 49 | lock = false 50 | } 51 | }, 52 | fail: () => { 53 | console.error("今日诗词-小程序SDK 获取 Token 失败,可能是网络问题或者您没有添加到域名白名单") 54 | } 55 | }) 56 | } 57 | } 58 | 59 | module.exports = { 60 | load: load 61 | } -------------------------------------------------------------------------------- /miniprogram/utils/request.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc API请求接口类封装 3 | * @author Aquan 4 | * @date 2019年7月29日17:38:06 5 | */ 6 | const app = getApp(); 7 | 8 | /** 9 | * POST请求API 10 | * @param {String} url 接口地址 11 | * @param {String} token 请求接口时的Token 12 | * @param {Object} params 请求的参数 13 | * @param {Object} sourceObj 来源对象 14 | * @param {Function} successFun 接口调用成功返回的回调函数 15 | * @param {Function} failFun 接口调用失败的回调函数 16 | * @param {Function} completeFun 接口调用结束的回调函数(调用成功、失败都会执行) 17 | */ 18 | function requestPostApi(url, token, params, sourceObj, successFun, failFun, completeFun) { 19 | requestApi(url, token, params, 'POST', sourceObj, successFun, failFun, completeFun) 20 | } 21 | 22 | /** 23 | * GET请求API 24 | * @param {String} url 接口地址 25 | * @param {String} token 请求接口时的Token 26 | * @param {Object} params 请求的参数 27 | * @param {Object} sourceObj 来源对象 28 | * @param {Function} successFun 接口调用成功返回的回调函数 29 | * @param {Function} failFun 接口调用失败的回调函数 30 | * @param {Function} completeFun 接口调用结束的回调函数(调用成功、失败都会执行) 31 | */ 32 | function requestGetApi(url, token, params, sourceObj, successFun, failFun, completeFun) { 33 | requestApi(url, token, params, 'GET', sourceObj, successFun, failFun, completeFun) 34 | } 35 | 36 | /** 37 | * 请求API 38 | * @param {String} url 接口地址 39 | * @param {Object} params 请求的参数 40 | * @param {String} method 请求类型 41 | * @param {Object} sourceObj 来源对象 42 | * @param {Function} successFun 接口调用成功返回的回调函数 43 | * @param {Function} failFun 接口调用失败的回调函数 44 | * @param {Function} completeFun 接口调用结束的回调函数(调用成功、失败都会执行) 45 | */ 46 | function requestApi(url, token, params, method, sourceObj, successFun, failFun, completeFun) { 47 | // console.log(token); 48 | if (method == 'POST') { 49 | // var contentType = 'application/x-www-form-urlencoded' 50 | var contentType = 'application/json' 51 | } else { 52 | var contentType = 'application/json' 53 | } 54 | wx.request({ 55 | url: url, 56 | method: method, 57 | data: params, 58 | header: { 59 | 'Content-Type': contentType, 60 | 'API-Authorization': token, 61 | 'ADMIN-Authorization': token, 62 | }, 63 | success: function (res) { 64 | typeof successFun == 'function' && successFun(res.data, sourceObj); 65 | }, 66 | fail: function (res) { 67 | typeof failFun == 'function' && failFun(res.data, sourceObj) 68 | }, 69 | complete: function (res) { 70 | typeof completeFun == 'function' && completeFun(res.data, sourceObj) 71 | } 72 | }) 73 | } 74 | 75 | module.exports = { 76 | requestPostApi, 77 | requestGetApi 78 | } 79 | -------------------------------------------------------------------------------- /miniprogram/utils/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * new Date() ---> 转化为 年 月 日 时 分 秒 3 | * let date = new Date(); 4 | * date: 传入参数日期 Date 5 | */ 6 | function formatTime(date) { 7 | var year = date.getFullYear() 8 | var month = date.getMonth() + 1 9 | var day = date.getDate() 10 | 11 | var hour = date.getHours() 12 | var minute = date.getMinutes() 13 | var second = date.getSeconds() 14 | 15 | 16 | return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':') 17 | } 18 | 19 | function formatNumber(n) { 20 | n = n.toString() 21 | return n[1] ? n : '0' + n 22 | } 23 | 24 | /** 25 | * 时间戳转化为年 月 日 时 分 秒 26 | * number: 传入时间戳 27 | * format:返回格式,支持自定义,但参数必须与formateArr里保持一致 28 | */ 29 | function customFormatTime(number, format) { 30 | 31 | var formateArr = ['Y', 'M', 'D', 'h', 'm', 's']; 32 | var returnArr = []; 33 | 34 | var date = new Date(number); 35 | returnArr.push(date.getFullYear()); 36 | returnArr.push(formatNumber(date.getMonth() + 1)); 37 | returnArr.push(formatNumber(date.getDate())); 38 | 39 | returnArr.push(formatNumber(date.getHours())); 40 | returnArr.push(formatNumber(date.getMinutes())); 41 | returnArr.push(formatNumber(date.getSeconds())); 42 | 43 | for (var i in returnArr) { 44 | format = format.replace(formateArr[i], returnArr[i]); 45 | } 46 | return format; 47 | } 48 | 49 | module.exports = { 50 | formatTime: formatTime, 51 | customFormatTime: customFormatTime 52 | } -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "miniprogram/", 3 | "cloudfunctionRoot": "cloudfunctions/", 4 | "description": "项目配置文件", 5 | "packOptions": { 6 | "ignore": [] 7 | }, 8 | "setting": { 9 | "urlCheck": true, 10 | "es6": true, 11 | "enhance": false, 12 | "postcss": true, 13 | "preloadBackgroundData": false, 14 | "minified": true, 15 | "newFeature": true, 16 | "coverView": true, 17 | "nodeModules": false, 18 | "autoAudits": false, 19 | "showShadowRootInWxmlPanel": true, 20 | "scopeDataCheck": false, 21 | "uglifyFileName": false, 22 | "checkInvalidKey": true, 23 | "checkSiteMap": true, 24 | "uploadWithSourceMap": true, 25 | "compileHotReLoad": false, 26 | "useMultiFrameRuntime": true, 27 | "useApiHook": true, 28 | "useApiHostProcess": false, 29 | "babelSetting": { 30 | "ignore": [], 31 | "disablePlugins": [], 32 | "outputPath": "" 33 | }, 34 | "enableEngineNative": false, 35 | "bundle": false, 36 | "useIsolateContext": true, 37 | "useCompilerModule": false, 38 | "userConfirmedUseCompilerModuleSwitch": false, 39 | "userConfirmedBundleSwitch": false, 40 | "packNpmManually": false, 41 | "packNpmRelationList": [], 42 | "minifyWXSS": true 43 | }, 44 | "compileType": "miniprogram", 45 | "libVersion": "2.17.0", 46 | "appid": "", 47 | "projectname": "meow", 48 | "debugOptions": { 49 | "hidedInDevtools": [] 50 | }, 51 | "isGameTourist": false, 52 | "simulatorType": "wechat", 53 | "simulatorPluginLibVersion": {}, 54 | "condition": { 55 | "search": { 56 | "list": [] 57 | }, 58 | "conversation": { 59 | "list": [] 60 | }, 61 | "plugin": { 62 | "list": [] 63 | }, 64 | "game": { 65 | "currentL": -1, 66 | "list": [] 67 | }, 68 | "gamePlugin": { 69 | "list": [] 70 | }, 71 | "miniprogram": { 72 | "list": [ 73 | { 74 | "id": 0, 75 | "name": "WeHalo", 76 | "pathName": "pages/wehalo/wehalo", 77 | "query": "", 78 | "scene": null 79 | }, 80 | { 81 | "id": -1, 82 | "name": "仪表盘", 83 | "pathName": "pages/halo/halo", 84 | "query": "", 85 | "scene": null 86 | }, 87 | { 88 | "id": 2, 89 | "name": "POST", 90 | "pathName": "pages/post/post", 91 | "query": "postId=15", 92 | "scene": null 93 | }, 94 | { 95 | "id": -1, 96 | "name": "关注公众号", 97 | "pathName": "pages/index/index", 98 | "query": "", 99 | "scene": 1011 100 | }, 101 | { 102 | "id": 4, 103 | "name": "Friends", 104 | "pathName": "pages/friends/friends", 105 | "query": "", 106 | "scene": null 107 | }, 108 | { 109 | "id": 5, 110 | "name": "journal", 111 | "pathName": "pages/journal/journal", 112 | "query": "", 113 | "scene": null 114 | } 115 | ] 116 | } 117 | } 118 | } --------------------------------------------------------------------------------