From e0299656e87b7614eeb4d84dff930f25a700d806 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Jul 2023 23:31:51 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20build(=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=9B=B4=E6=96=B0):=20=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC=20C?= =?UTF-8?q?ST=202023-07-11=20Tuesday=2023:31:51=20Updated=20By=20GitHub=20?= =?UTF-8?q?Actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 19 + CNAME | 1 + LICENSE | 427 ++++++++++++++++++ about/index.html | 19 + ads.txt | 1 + archives/2020/index.html | 19 + archives/2021/index.html | 19 + archives/2022/index.html | 19 + archives/2023/index.html | 19 + archives/index.html | 19 + assets/mmedia/mmedia-loader.js | 1 + atom.xml | 1 + baidusitemap.xml | 1 + blogroll/index.html | 19 + brokenlinks.txt | 0 categories/index.html | 19 + .../\345\215\232\345\256\242/index.html" | 19 + .../\345\217\260\346\271\276/index.html" | 19 + .../\345\255\246\344\271\240/index.html" | 19 + .../\345\267\245\344\275\234/index.html" | 19 + .../\345\267\245\345\205\267/index.html" | 19 + .../\347\224\237\346\264\273/index.html" | 19 + .../\351\237\263\344\271\220/index.html" | 19 + css/custom.css | 1 + css/index.css | 1 + css/var.css | 0 essay/index.html | 19 + essay/speak/index.html | 21 + favicon.ico | Bin 0 -> 18092 bytes index.html | 19 + js/custom.js | 1 + js/main.js | 1 + js/search/algolia.js | 1 + js/search/local-search.js | 1 + js/tw_cn.js | 1 + js/utils.js | 1 + manifest.json | 1 + moments/index.html | 19 + music/index.html | 19 + newPost.json | 1 + offline/index.html | 19 + page/2/index.html | 19 + page/3/index.html | 19 + page/4/index.html | 19 + posts/2fa-last-security-line/index.html | 19 + posts/56th-golden-bell-awards/index.html | 19 + .../index.html | 19 + posts/about-pts/index.html | 19 + .../index.html | 19 + .../index.html | 19 + posts/awesome-status-pages/index.html | 19 + posts/ccs-work-diary-part1/index.html | 19 + posts/ccs-work-diary-part2/index.html | 20 + posts/ccs-work-diary-part3/index.html | 19 + posts/course-design/index.html | 19 + posts/cusdis-or-disqus/index.html | 19 + .../index.html | 19 + .../index.html | 19 + .../index.html | 19 + posts/hexo-butterfly-algolia/index.html | 19 + posts/hexo-toss/index.html | 19 + posts/hexo-webpushr-notification/index.html | 19 + .../index.html | 19 + .../index.html | 19 + .../index.html | 20 + posts/i-dont-really-want-html/index.html | 19 + .../index.html | 19 + .../index.html | 19 + .../index.html | 19 + posts/production-practice/index.html | 19 + .../index.html | 19 + posts/resume-template/index.html | 19 + .../index.html | 19 + posts/special-test-article/index.html | 19 + posts/ta-said-nothing/index.html | 19 + posts/the-real-addthis/index.html | 19 + .../the-webp-road-of-blog-pictures/index.html | 19 + .../index.html | 19 + .../index.html | 19 + .../index.html | 19 + .../index.html | 19 + posts/yuque-to-hexo/index.html | 19 + privacy-policy/index.html | 19 + robots.txt | 5 + rss.xml | 1 + sitemap.txt | 52 +++ sitemap.xml | 1 + sub/index.html | 19 + sw.js | 145 ++++++ tags/index.html | 19 + "tags/\345\215\232\345\256\242/index.html" | 19 + "tags/\345\217\260\346\271\276/index.html" | 19 + "tags/\345\255\246\344\271\240/index.html" | 19 + "tags/\345\267\245\344\275\234/index.html" | 19 + "tags/\345\267\245\345\205\267/index.html" | 19 + "tags/\347\224\237\346\264\273/index.html" | 19 + "tags/\351\237\263\344\271\220/index.html" | 19 + will/index.html | 19 + 98 files changed, 2056 insertions(+) create mode 100644 404.html create mode 100644 CNAME create mode 100644 LICENSE create mode 100644 about/index.html create mode 100644 ads.txt create mode 100644 archives/2020/index.html create mode 100644 archives/2021/index.html create mode 100644 archives/2022/index.html create mode 100644 archives/2023/index.html create mode 100644 archives/index.html create mode 100644 assets/mmedia/mmedia-loader.js create mode 100644 atom.xml create mode 100644 baidusitemap.xml create mode 100644 blogroll/index.html create mode 100644 brokenlinks.txt create mode 100644 categories/index.html create mode 100644 "categories/\345\215\232\345\256\242/index.html" create mode 100644 "categories/\345\217\260\346\271\276/index.html" create mode 100644 "categories/\345\255\246\344\271\240/index.html" create mode 100644 "categories/\345\267\245\344\275\234/index.html" create mode 100644 "categories/\345\267\245\345\205\267/index.html" create mode 100644 "categories/\347\224\237\346\264\273/index.html" create mode 100644 "categories/\351\237\263\344\271\220/index.html" create mode 100644 css/custom.css create mode 100644 css/index.css create mode 100644 css/var.css create mode 100644 essay/index.html create mode 100644 essay/speak/index.html create mode 100644 favicon.ico create mode 100644 index.html create mode 100644 js/custom.js create mode 100644 js/main.js create mode 100644 js/search/algolia.js create mode 100644 js/search/local-search.js create mode 100644 js/tw_cn.js create mode 100644 js/utils.js create mode 100644 manifest.json create mode 100644 moments/index.html create mode 100644 music/index.html create mode 100644 newPost.json create mode 100644 offline/index.html create mode 100644 page/2/index.html create mode 100644 page/3/index.html create mode 100644 page/4/index.html create mode 100644 posts/2fa-last-security-line/index.html create mode 100644 posts/56th-golden-bell-awards/index.html create mode 100644 posts/a-simple-but-not-simple-m3u8-download-tool/index.html create mode 100644 posts/about-pts/index.html create mode 100644 posts/about-the-55th-golden-bell-awards/index.html create mode 100644 posts/add-email-subscription-to-your-hexo-blog/index.html create mode 100644 posts/awesome-status-pages/index.html create mode 100644 posts/ccs-work-diary-part1/index.html create mode 100644 posts/ccs-work-diary-part2/index.html create mode 100644 posts/ccs-work-diary-part3/index.html create mode 100644 posts/course-design/index.html create mode 100644 posts/cusdis-or-disqus/index.html create mode 100644 posts/digital-watermark-detection-based-on-wavelet-transform/index.html create mode 100644 posts/github-automatically-merges-pull-requests-notes/index.html create mode 100644 posts/google-adsense-configuration-manual/index.html create mode 100644 posts/hexo-butterfly-algolia/index.html create mode 100644 posts/hexo-toss/index.html create mode 100644 posts/hexo-webpushr-notification/index.html create mode 100644 posts/how-to-ask-questions-the-smart-way/index.html create mode 100644 posts/how-to-enjoy-joox-music-service-in-mainland-china/index.html create mode 100644 posts/how-to-hide-hexo-articles-gracefully/index.html create mode 100644 posts/i-dont-really-want-html/index.html create mode 100644 posts/implementation-of-simple-browser-update-push/index.html create mode 100644 posts/introduction-of-plugin-tags-based-on-butterfly/index.html create mode 100644 posts/playlist-conversion-of-major-music-platforms/index.html create mode 100644 posts/production-practice/index.html create mode 100644 posts/research-on-image-denoising-technology-based-on-wavelet-transform/index.html create mode 100644 posts/resume-template/index.html create mode 100644 posts/song-about-you-live-in-the-sky-2023/index.html create mode 100644 posts/special-test-article/index.html create mode 100644 posts/ta-said-nothing/index.html create mode 100644 posts/the-real-addthis/index.html create mode 100644 posts/the-webp-road-of-blog-pictures/index.html create mode 100644 posts/uptime-free-website-survival-monitoring/index.html create mode 100644 posts/waline-comments-system-deployment-logs/index.html create mode 100644 posts/why-did-i-choose-tidio-as-the-chat-system/index.html create mode 100644 posts/why-github-actions-is-so-popular/index.html create mode 100644 posts/yuque-to-hexo/index.html create mode 100644 privacy-policy/index.html create mode 100644 robots.txt create mode 100644 rss.xml create mode 100644 sitemap.txt create mode 100644 sitemap.xml create mode 100644 sub/index.html create mode 100644 sw.js create mode 100644 tags/index.html create mode 100644 "tags/\345\215\232\345\256\242/index.html" create mode 100644 "tags/\345\217\260\346\271\276/index.html" create mode 100644 "tags/\345\255\246\344\271\240/index.html" create mode 100644 "tags/\345\267\245\344\275\234/index.html" create mode 100644 "tags/\345\267\245\345\205\267/index.html" create mode 100644 "tags/\347\224\237\346\264\273/index.html" create mode 100644 "tags/\351\237\263\344\271\220/index.html" create mode 100644 will/index.html diff --git a/404.html b/404.html new file mode 100644 index 000000000..e105a8e5a --- /dev/null +++ b/404.html @@ -0,0 +1,19 @@ +页面没有找到 | CC的部落格
Page not found

404

Oops! 页面不存在~
\ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..39a653f9a --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +github.blog.ccknbc.cc \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..3b7b82d0d --- /dev/null +++ b/LICENSE @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/about/index.html b/about/index.html new file mode 100644 index 000000000..03476a966 --- /dev/null +++ b/about/index.html @@ -0,0 +1,19 @@ +关于本站 | CC的部落格

关于本站

镜像站点

以下排名不分先后,请选择适合自己访问较快的即可
GitHub | GitLab | Gitee | Bitbucket | Vercel | Netlify | CloudFlare | Zeabur

站点源码

可前往以下地址查看源码
GitHub | GitLab | JihuLab | Bitbucket | Coding | Gitee


评论

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
\ No newline at end of file diff --git a/ads.txt b/ads.txt new file mode 100644 index 000000000..32af2877d --- /dev/null +++ b/ads.txt @@ -0,0 +1 @@ +google.com, pub-4962482948943075, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/archives/2020/index.html b/archives/2020/index.html new file mode 100644 index 000000000..92e959269 --- /dev/null +++ b/archives/2020/index.html @@ -0,0 +1,19 @@ +2020 | CC的部落格
\ No newline at end of file diff --git a/archives/2021/index.html b/archives/2021/index.html new file mode 100644 index 000000000..4d610fc79 --- /dev/null +++ b/archives/2021/index.html @@ -0,0 +1,19 @@ +2021 | CC的部落格
\ No newline at end of file diff --git a/archives/2022/index.html b/archives/2022/index.html new file mode 100644 index 000000000..3c2a7a671 --- /dev/null +++ b/archives/2022/index.html @@ -0,0 +1,19 @@ +2022 | CC的部落格
\ No newline at end of file diff --git a/archives/2023/index.html b/archives/2023/index.html new file mode 100644 index 000000000..9f1c0c528 --- /dev/null +++ b/archives/2023/index.html @@ -0,0 +1,19 @@ +2023 | CC的部落格
文章总览 - 1
2023
2023《好好》线上演唱会
2023《好好》线上演唱会
\ No newline at end of file diff --git a/archives/index.html b/archives/index.html new file mode 100644 index 000000000..65780a45e --- /dev/null +++ b/archives/index.html @@ -0,0 +1,19 @@ +归档 | CC的部落格
\ No newline at end of file diff --git a/assets/mmedia/mmedia-loader.js b/assets/mmedia/mmedia-loader.js new file mode 100644 index 000000000..d032df83c --- /dev/null +++ b/assets/mmedia/mmedia-loader.js @@ -0,0 +1 @@ +var initMmedia=function(){function o(n){return n.filter(function(n,e,t){return t.indexOf(n)===e})}var a=HEXO_MMEDIA_DATA||void 0;a&&function(r,a){return new Promise(function(n,e){var t=new Array;r&&0CC的部落格https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/logo/logo.pngCC的部落格,CC康纳百川的小窝,与你分享二三事CC康纳百川2023-06-25T12:44:00.000Zhttps://blog.ccknbc.cc/CC康纳百川blog@ccknbc.ccCC的部落格Copyright © 2020-present CC康纳百川 All rights reserved.你以为 AddThis 只是个分享工具吗?https://blog.ccknbc.cc/posts/the-real-addthis/2021-05-15T13:00:00.000Z2023-06-25T12:44:00.000Z本文首发在语雀,自动同步更新至CC 的部落格

本文作废

Notice of Termination of AddThis Services.

What’s Changing?

As part of a periodic product portfolio review, Oracle has made the business decision to terminate all AddThis services effective as of May 31, 2023.

Key Dates

Existing AddThis users can expect that after May 31, 2023:

  • the user must immediately cease its use of AddThis services, and promptly remove all AddThis related code and technology from its websites;
  • AddThis buttons may disappear from the user’s websites;
  • the AddThis dashboard associated with the user’s registration for AddThis, and all support for AddThis services, will no longer be available;
  • all features of AddThis configured to interoperate with user’s websites, any other Oracle services, or any third-party tools and plug-ins will no longer function.

Oracle thanks you for your attention and understanding in this matter, and for the many years of allowing Oracle to provide this service to you.

How Do I Uninstall the AddThis Button?

If you’ve copied and pasted the code into your website, go back into the code and look for and , then delete these lines and any code between them. If you’ve used another method to install AddThis on your page, please contact us and we’ll be happy to help you.

总结:终止服务,主题已移除

Butterfly 如何使用

打开 AddThis 官网,标语是 Turn your visitors into engaged customers. 听起来是个营销工具,但主题集成的时候选择了它,并且没有做特别说明,只是让我们找到 pub-id ,并没有说如何配置

实际上要想和 AddToAny 或者 sharejs 一样使用文章内分享,我们得在控制台添加 Tools,就像下图所示然后选择行内工具后面样式部分就根据自己喜好和需求按钮多少,在哪些页面显示等来自行配置啦。比如我还同时选择了,自动展开分享按钮。而且他能很好的自适应,并且后台修改之后我们博客无需任何操作即可更新。

其他工具

但还有其他工具也很好用,比如你点进文章来之前,应该有弹窗提示你要阅读隐私政策,实际上这是链接推广工具的活用。再比如放在顶栏作为临时公告,并且都有很好的自适应人性化选择,你下滑就会收起来,上滑再弹出。同样如果你是文章页或者订阅页面,因为我配置了仅在这些页面显示,会弹出一个订阅文章更新弹窗,这里收集邮件工具派上了用场,并且与 Mailchimp 配合完成了这项工作,至于配置邮件订阅,可以查看之前的文章 为你的 Hexo 博客添加邮件订阅不过为了邮件订阅,我同样整合到了 Tidio,详情见订阅页面。当然如果你也在乎其他平台的关注数量,可以使用关注按钮来实现推广效果,文章推荐和打赏这里还是建议使用主题自带的就好。此外它还配有统计分析工具(这里强烈推荐您阅读 隐私政策),以帮助你实现更好的内容转化。所以结合起来正常情况下我开起了五个工具当需要发布临时公告时,我会根据重要程度选择左下角或者顶栏就免费来说,他做的很不错了,相比于专门做弹窗的 poptin 似乎更简单的与 mailchimp 集成,但毕竟术业有专攻,比弹窗肯定不如人家,不过白嫖来说已经够了,我也不用使用 snackbar 刷新 jsd 缓存来实现临时公告了。而我现在重新使用了 webpushr 来实现浏览器通知,不管是否订阅,我均可以发送公告,并可保留最近 3 条公告,然后这就涉及到了空间利用率和用户体验的问题,所以我就得考虑关闭一些小部件,比如邮件订阅弹窗(据说会影响搜索引擎权重),还有分享按钮。电脑上无所谓,手机上显得有点挤(不过可以选择根据设备或者宽度自适应是否显示),即使我放在右下角,分享按钮放在左下角。所以我在公告栏加入了邮件订阅表格,并添加链接导向订阅页,但毕竟也没人订阅,还是链接导向订阅页面吧。

]]>
本文介绍了 AddThis 的使用https://blog.ccknbc.cc/posts/the-real-addthis/#post-comment
Hexo浏览器定向推送文章更新https://blog.ccknbc.cc/posts/hexo-webpushr-notification/2022-10-04T16:00:00.000Z2023-06-25T12:25:00.000Z查看本文语雀版本【首发】,自动同步更新至CC 的部落格

两年前,我刚开始使用Hexo的时候,写了一篇文章简单浏览器更新推送的实现,最近登录webpushr控制台,发现其支持按话题topic指定推送了,而原来的插件一直没有更新,且对个人的写作习惯不是很友好,所以对原插件进行了修改,并发布到了NPM

欢迎大家前往订阅页面选择合适的订阅方式,关于邮件订阅,现已支持分类订阅

安装

推荐使用 npm 以插件形式安装

npm i hexo-webpushr-notification

自定义修改

当然你也可以自定义修改webpushr.js文件后,再安装相关需要依赖,然后将文件放到Hexo/scripts/目录下即可正常运行,CC 本人亦是如此对于 0.2.0 以上版本,您只需要在 Hexo 所在目录安装 axios 即可,这样测试相较于安装 GitHub 更方便(以及欢迎 PR )

npm i axios

使用

在你的 Hexo 根目录配置文件 _config.yml中添加如下内容,可按需配置,建议前往 README 查看最新配置

webpushr:
enable: true

webpushrKey: "webpushrKey"
webpushrAuthToken: "webpushrAuthToken"
# 出于安全考虑,建议将上述两个重要参数添加至系统全局环境变量,并删除或注释掉此处配置
# 否则可在网页端向访问者或订阅用户发送推送 https://www.webpushr.com/api-playground
# 例如GitHub Actions环境变量配置,参数名不变,密钥名自定义,可参考如下
# env:
# webpushrKey: ${{ secrets.WEBPUSHR_KEY }}
# webpushrAuthToken: ${{ secrets.WEBPUSHR_AUTH_TOKEN }}
# 如果您的仓库私有,则无需担心此问题

trackingCode: "trackingCode"
icon: "https://.../192.png" # 必须为 HTTPS 以及 192*192 png图片
# auto_hide: false # 默认为 1,代表true,即自动隐藏
# sort: "date" # 默认为updated,即只要最新文章更改了更新时间即推送新文章,改为date即文章第一次发布时间
# delay: "0" # 延时推送,考虑到CDN缓存更新,默认定时为在 hexo d 10分钟后推送,单位为分钟(最短延时为5分钟,设置 0 则会立即推送)
# expire: "15d" # 推送过期时长,默认值为7天,格式如下:'5m'代表5分钟,'5h'代表5小时, '5d'代表5天.
# image: # 默认为文章封面,Front-matter 属性为'cover'(butterfly主题友好选项),如果您没有定义默认封面或此属性,请在这里设置默认image
action_buttons: # 如果你需要额外自定义按钮 可按照如下格式:
- title: 阅读全文 # 当 title 未配置时 默认值为 “前往查看”
# url: # 当 url 未配置时 默认值为 最新文章链接
- title: 订阅页面
url: https://blog.ccknbc.cc/sub/
# 当 action_buttons 未定义时也默认保留了一个“前往查看”按钮,除非设置为 false
# action_buttons: false # 当设为 false 则不显示额外的按钮,因为隐藏按钮即为当前文章链接

# 以下配置为按订阅主题推送给不同订阅用户,请按照数组形式,一一对应,具体位置请看使用文档
categories: [工作, 博客, 工具, 生活, 音乐, 学习]
segment: ["484223", "484224", "484225", "484226", "484227", "484229"]
endpoint: segment # 可选配置 all / segment / sid
# 默认为 segment,即根据不同主题推送细分,同时配置上述选项
# 例如 all,即推送至所有用户;针对本地测试,建议只推送给单个用户即自己,同时设置下方的 sid 值
# 您也可以将segment 设置为 all-users 对应的ID,同样也可以实现推送至所有用户
sid: "119810055" # 单个用户ID 可在控制台查看 https://app.webpushr.com/subscribers


# 此外,在文章 Front-Matter 处
# 可覆盖 auto_hide 和 expire 配置,针对需要特别提醒文章可以设置不自动隐藏及过期时间延长等操作
# 以及可指定schedule参数(例如:schedule: 2022-10-01 00:00:00),定时推送
# 当文章头设置 webpushr: false 时,可关闭本篇文章推送,此参数主要防止久远文章更改更新时间后自动推送
  1. 前往 webpushr 控制台获取如下参数,注册的时候可能会遇到一点困难,中国大陆用户需要科学上网来加载验证服务)
  2. 关于注册及一些具体内容,可以看之前的文章 简单浏览器更新推送的实现
  3. 依次点击 Integration > REST API Keys,即可看到你的webpushrKeywebpushrAuthToken
  4. 依次点击 Setup > TrackingCode,可以看到如下代码
<!-- start webpushr tracking code -->
<script>(function(w,d, s, id) {if(typeof(w.webpushr)!=='undefined') return;w.webpushr=w.webpushr||function(){(w.webpushr.q=w.webpushr.q||[]).push(arguments)};var js, fjs = d.getElementsByTagName(s)[0];js = d.createElement(s); js.id = id;js.async=1;js.src = "https://cdn.webpushr.com/app.min.js";
fjs.parentNode.appendChild(js);}(window,document, 'script', 'webpushr-jssdk'));
webpushr('setup',{'key':'BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58' });</script>
<!-- end webpushr tracking code -->

最后一行BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58 就是你的 trackingCode

注意:因权限问题,本地测试时(hexo s)可能不会显示弹窗,但如果你配置了小铃铛,小铃铛会显示

额外配置

因官方 sw 脚本注册后,我们无法注册自己的 sw 脚本,但官方提供了配置,方便我们使用 sw 的缓存,拦截请求等功能

首先在配置项中添加 sw_self: true 配置,开启自行注册 sw(默认用户不用添加或者设为 false

webpushr:
sw_self: true

另外,你还需要在你的脚本文件(例如sw.js)中引入

importScripts('https://cdn.webpushr.com/sw-server.min.js');

完成这些你就可以自行注册你的sw脚本了,如果你需要了解如何编写或注册service worker脚本,可以参考以下文章或项目hexo-swpp
Service Worker
clientworker
Workbox

自定义

个人建议将控制台右上角小铃铛 🔔 里全部配置一遍以获得更好的效果

你需要自定义一些参数才可以使用根据不同主题,按照订阅者订阅话题推送功能(目前根据个人需求是这个设置,默认行为为当未匹配到对应分类时不推送文章,而不是向所有用户推送文章,当然你也可以配置目标为所有用户)

在控制台,点击Setup>Opt-In Prompt ,向下滑动打开Enable Topics(小铃铛样式无此选项,因此推荐您使用前两种样式),并新增几个主题,对应你想推送的文章分类即可

然后点击Users>Segments ,即可获取对应的segment关系,依次填入配置项即可

工作原理

当你运行hexo generate插件会在public 目录生成 newPost.json 这样一个文件. newPost.json 包含了一些你想推送的新文章相关信息,示例格式如下

{
"title": "Hexo浏览器定向推送文章更新",
"updated": "2023-04-22T20:25:00+08:00",
"message": "这一次,CC的部落格可以根据读者订阅主题定向推送了,并且实现了NPM插件化",
"target_url": "https://blog.ccknbc.cc/posts/hexo-webpushr-notification/",
"image": "https://pic1.afdiancdn.com/user/8a7f563c2e3811ecab5852540025c377/common/d2a947d48815ed24936a919873b97841_w1366_h768_s31.png",
"categories": ["博客"],
"schedule": "2023-06-13T15:16:41.187Z",
"expire": "7d",
"auto_hide": "1"
}

而他的来源就是我们在文章开头Front-Matter自定义的那些属性,而本插件针对Butterfly主题做了针对性修改,您也可以在您的模板文件目录下修改文章模板文件(Hexo/scaffolds/post.md),主要针对性参数如下

date:
updated:
schedule: 对应配置项中定时推送时间
auto_hide: 对应配置项中是否自动隐藏
expire: 对应配置项中过期时间
categories: 文章分类
description: 对应配置项中message,即文章描述
cover: 对应配置项中image,默认选取文章封面

如果你的主题不是采用默认的date updated 参数,记得补充,因为这是判断最新文章的依据

如果你习惯了使用截断的方式,也无需配置description继续使用,示例如下,注意<!-- more -->

---
title: Hexo使用Web Push Notification 浏览器通知推送
tags:
- hexo
- 服务器推送技术
- push notifications
categories:
- 开发
comments: true
abbrlink: 98ae9e55
date: 2020-02-26 10:00:00
---

Web Push Notification 是怎么工作的?个人博客为什么要使用它?如何使用它?

<!-- more -->

当执行 hexo deploy命令时,插件会比较在线版本和本地版本newPost.json中最新文章更新时间是否一致,如果不同,则插件将推送最新文章更新通知(默认为十分钟后推送)

注意:如果您是第一次使用本地测试应该看到

INFO  无文章更新 或 为首次推送更新

这是正常现象,因为此时你的网站还没有newPost.json这个文件,后续有更新时将正常推送,你可以先推送一次,再修改更新时间测试一次,当然建议测试目标选择自己,即 sid 选项配置

当然如果您在使用过程中有什么问题或遇到了 Bug 也欢迎随时在评论区或issues反馈,当然因为本人是菜鸡,所以有大佬 PR 最好了

推送效果

因为我是通知自动隐藏后才截图,所以大致效果如下所示

后续计划

  • 兼容自定义Service Work的功能,因为webpushr-sw.js优先注册的原因,只能有一个 sw注册,无法注册自己编写脚本。
  • 支持参数更多的可自定义,启用或关闭。例如不延时,立即发送;不显示按钮(因为默认就是跳转到文章)等
  • 目前的判断逻辑,虽然可以根据更新时间来判断,但如果很久之前的文章翻新,只要更新时间最新,也会触发推送,主要针对 updated 方式,还没想到好的解决办法,目前就是确认需要推送才更改更新时间咯
]]>
这一次,CC的部落格可以根据读者订阅主题定向推送了,并且实现了NPM插件化https://blog.ccknbc.cc/posts/hexo-webpushr-notification/#post-comment
2023《好好》线上演唱会https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/2023-03-08T12:30:00.000Z2023-03-12T09:00:00.000Z

版权归属 台湾 相信音乐

刘若英 X 苏慧伦 X 丁当 X 白安

2023《好好》线上演唱会

Song About You live in the sky 2023

歌单一览

已在视频中标出


苏慧伦 part

0:30 鸭子

4:27 被动

8:18 说话

9:09 严重

13:12 说话

13:24 恋恋真言

17:17 在我生命中的每一天 feat.丁当


丁当 part

21:58 开头

22:39 夜猫

26:13 花火

30:18 说话

31:07 猜不透

35:12 说话

37:25 女字旁

41:56 我爱他


白安 part

46:54 不够特别的我不要

51:41 刚好

56:01 说话

56:39 是什么让我遇见这样的你

1:00:39 没有人写歌给你过吧

1:05:39 让我逃离平庸的生活


刘若英 part

1:10:25 所有相爱的人啊

1:14:28 成全

1:18:57 说话

1:20:55 固执

1:25:47 缩影

1:29:30 talking feat.白安

1:31:20 妈妈 feat.白安

1:35:51 后来

1:40:52 快乐天堂 feat.苏慧伦、丁当、白安


女加上子 每个女子生而为好

该对自己好 该好好疼爱自己

女子女子 就是好好

好歌相伴 好上加好

《好好》线上演唱会

一场女子们的闺密音乐聚会

宜尽兴 宜微醺 宜舒心 宜走心

妳有多久没有好好跟自己说说话了?

妳有多久没有好好聆听心底声音了?

妳有多久没有好好跟好友聊聊天了?

妳有多久没有好好欣赏美好事物了?

女子,要好好去爱,更要好好爱自己。

「3 月 8 日」是一年一度的「国际妇女节」 (International Women’s Day),提醒每个女子要爱自己,更能去爱别人、去爱这个世界。 在这个这个专属于女子的节日,刘若英 X 苏慧伦 X 丁当 X 白安,四个女子的美好相遇,要在 38 妇女节的周三夜,以音乐用心地打造出一场属于每个你的 “Lady’s Night”,你可以与你自己,也可以与好闺密们,一起好好享受、好好尽欢、好好聆听一首首动人的女子心声。

如水 如石 如光 如树

一场音乐与自然的飨宴

将美好谱写 如歌而行

当音乐遇见自然 当内心遇见自己

美的时节 好的相遇

女子女子 好好与你以歌相聚

「女」加上「子」等于「好」,「女子」加上「女子」就是「好好」,好上加好! 「好好女声」刘若英、苏慧伦、丁当、白安,春暖花开时节献唱,,以歌相聚在《好好》线上演唱会,不仅渲染多首个人经典好歌,彼此间更有精彩的合唱新火花! 《好好》演唱会以「女野」概念,结合「水、石、光、树」为主题,女子在自然旷野里吟唱,呈现出如水之柔美、如石之坚强、如光之魔幻、如树之实在的演唱氛围。

新的一年一切都在慢慢变好,刘若英、苏慧伦、丁当、白安,四美女子以美好歌声陪伴每个认真生活、认真爱的女子,一起告别因疫情闷久的坏坏情绪,迎接温暖美丽的好好心情

视频版

流媒体平台

QQ 音乐 | 网易云音乐 | 酷狗音乐 | 酷我音乐 | 咪咕音乐 | 汽水音乐

]]>
刘若英X苏慧伦X丁当X白安 2023《好好》线上演唱会 Song About You live in the sky 2023https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/#post-comment
Hexo Butterfly Algolia 搜索的使用https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/2021-05-11T03:00:00.000Z2023-02-16T11:11:40.000Z本文介绍了 Hexo Butterfly 主题下 Algolia 搜索的使用

本文首发在语雀自动同步更新至CC 的部落格

注册账号

前往 Algolia 官网注册一个账号,新建 应用和 index数据中心建议选择新加坡或香港,当然根据你自己情况而定

安装插件

npm install hexo-algolia --save
npm install hexo-algoliasearch --save

分别是 hexo-algoliahexo-algoliasearch,他们的介绍分别为

Index your hexo website content to Algolia Search.
🔎 A plugin to index posts of your Hexo blog on Algolia

也就很明显了,如果你想要全站搜索可选择前者,如果你只想搜索文章两者兼可。但前者不能将文章内容作为索引上传(其实老版本是支持的,但因为索引大小限制,在新版本取消索引了文章内容),后者目前仍可全文上传。然后就是 HEXO 配置文件中添加以下内容,下文基本以 hexo-algoliasearch 为例,因为我个人认为访客只会搜文章吧(事实上是搜索根本没人用,毕竟也根本没人访问),hexo-algolia 可查看官方文档,注意配置和命令的区别

_config.yml :

algolia:
appId: "Z7A3XW4R2I"
apiKey: "12db1ad54372045549ef465881c17e743"
adminApiKey: "40321c7c207e7f73b63a19aa24c4761b"
chunkSize: 5000
indexName: "my-hexo-blog"
fields:
- content:strip:truncate,0,500
- excerpt:strip
- gallery
- permalink
- photos
- slug
- tags
- title

为了保险,识别到插件,还可以加入以下内容

plugins:
- hexo-algoliasearch

去主题配置文件打开 Algolia 搜索,记得关闭本地搜索,二者只能取其一!

_config.butterfly.yml :

# Algolia search
algolia_search:
enable: true
hits:
per_page: 3

# Local search
local_search:
enable: false

然后来看以下具体的参数配置获取方式appIdapiKeyadminApiKey可在 API Keys 页面获取,注意保管好你的 Admin Key,不要让其他人知道,不建议直接写在配置中对于 Windows 系统,如果你不想每次都进行设定变量操作,可以添加ALGOLIA_ADMIN_API_KEY到系统的环境变量中而 hexo-algolia 插件环境变量名称为 HEXO_ALGOLIA_INDEXING_KEY 注意根据对应的文档更改,当然也可以使用命令行工具

# Windows
## 微软的 powershell)
$env:ALGOLIA_ADMIN_API_KEY = ""

## cmd
建议不用 cmd,正经人不用 cmd

# Linux
## sh/bash
export ALGOLIA_ADMIN_API_KEY=

## fish
set -xg ALGOLIA_ADMIN_API_KEY ""

如果你和我一样使用的自动部署,例如 Github Actions,你可以在工作流中一开始或者对应的步骤添加环境变量,记得 Secrets 中也要添加哦

jobs:
deploy:
name: Deploy Hexo Public To Pages
runs-on: ubuntu-latest
env:
TZ: Asia/Shanghai
ALGOLIA_ADMIN_API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }}

或者使用

export ALGOLIA_ADMIN_API_KEY=…
export HEXO_ALGOLIA_INDEXING_KEY=…

indexName 即你开始新建的索引名称其他内容保持默认即可,但对于fields

配置示例

这里选择不截取上传全文,并且删除 html 标签,只留下有用的搜索内容

fields:
- content:strip
- excerpt:strip
- gallery
- permalink
- photos
- slug
- tags
- title

但对于博客来说,没人会按照 tags photos(或者 cover)来搜索吧,所以有些内容不必要上传,并如果你和我一样有多个镜像站,在不改源码(algolia.js)的情况下,不会使用 permalink 而使用 path(改源码可以使用 slug,但没必要),并且只留下必要的内容,如下所示:

algolia:
appId: "947RX7HP3E"
apiKey: "9114b3fa2a3307b2cc8eec7e3ae5a8ea"
chunkSize: 5000
indexName: "ccknbc-blog"
fields:
- path
- title
- content:strip

这样有了标题,全文内容,路径即可在不同镜像站找到对应的页面,而不是跳到主站,当然你选择跳到主站无可厚非。

使用命令

hexo algolia
而在这之前还需要hexo g生成文件
所以具体使用命令就是
hexo cl && hexo g && hexo algolia
或者在未安装 HEXO CLI 的情况下使用以下命令
npm run clean && npm run build && hexo algolia -n && gulp

可选配置

是否删除之前建立好的索引重新建立索引?

hexo algolia -n
或者
hexo algolia --no-clear

注意查看命令行输出信息,然后去官网检查索引是否生成事实上到这里已经可以获得下图所示的搜索效果(这是冰老师博客的效果,它使用的是 hexo-algolia,毕竟有关于我界面)

Algolia 配置

这里不细节讲,你可以查阅官方文档,虽然有些过时的参数,但结合 Upgrade from v2 to v3 还是勉强能用,蝴蝶已经做好了高亮标题,虽然会查询文章内容,但并不会高亮文章内容节选,我们要做的就是修改部分 js 内容,并对应的设置好 Algolia,以便按照我们要求的优先顺序展示搜索结果,而不是默认的很奇怪的排序,毕竟针对中文分词他是一个一个分不能按照英语那样,针对英文我们可以开启分词查询,驼峰查找而不是盲目的匹配整个单词,并且允许拼错字母或汉字的情况存在,这些都是一个搜索系统要考虑的问题。然后针对搜索速度,我们可以对文章内容进行切片或者属性的刻画,但 V2 所支持的功能实在太少,派的上用场的大概就是 匹配的字词内容,匹配度,匹配内容的摘录(默认 10 个字词),还有高级搜索用法的启用。

JS 修改

主题 4.0.0 以下版本

到这里还没有结束,如果你这样操作就会有一个问题,假设你的访问流量很大,有很多人用搜索功能,那么免费的 1 万次搜索额度可能不够一个月的使用,需要按下ENTER键再执行搜索而不是实时搜索,因此可以稍作修改(blog\themes\butterfly\source\js\search\algolia.js) js 的部分内容,不想动源码的可以保存到其他与主题不冲突的路径,然后更换 CDN 地址即可主要修改以下内容,然后就是排版问题改了改位置,不喜欢的可以不改,很直白就不用过多解释了,这样就可获得和本博客一样的搜索效果了

  search.addWidget(
instantsearch.widgets.searchBox({
container: '#algolia-search-input',
reset: false,
magnifier: false,
+ searchOnEnterKeyPressOnly: true,
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder
})
)
search.addWidget(
instantsearch.widgets.hits({
container: '#algolia-hits',
templates: {
item: function (data) {
const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
return (
'<a href="' + link + '" class="algolia-hit-item-link"><b>' +
data._highlightResult.title.value + '</b><br>'
+ + data._snippetResult.contentStrip.value + '<br>( 匹配字词 : '
+ + data._highlightResult.contentStrip.matchedWords + ' ) | ( 匹配等级 : '
+ + data._highlightResult.contentStrip.matchLevel + ' )</a>'
)
},

主题 4.0.0 以上版本

已经升级到 V4 版本,那么一些特性就可以使用了,修改内容其实差不多,只是建议对于第 87 行的页数限制,主要是为了手机上排版美观,不会转到下一行,但是这样会有一个问题,如果结果超过 5 页,那么将无法显示,最后一页代表第 5 页,所以我个人会选择删掉这个参数限制,同时合并删除了部分代码,以及使用 widget 的 powerby 组件而不是官方的 svg 代码解决方案。另外因为新版官方的每次访问网站都会有一次全局请求,这在消耗免费额度的同时,也影响网站加载的速度,所以修改默认行为为按下回车后再请求同样的部分参数发生了改变(L55-59),可以自行比对或查看官方文档,也可以直接引用我的

特别提一嘴官方切片方式对我来说 140 个字太长了,所以如果可以接受就用官方的,不用做其他更改,但想要和我的显示方式一样,就注意配置好切片,默认是 10 个词符,毕竟有现成的切片高亮处理可以用,就没必要再来一次了

另外,新版浏览器支持搜索并定位高亮处理,所以对跳转链接也做了处理,算是弥补了一点不能精准定位的缺陷,比如点击如下链接它会跳转到搜索结果对应的位置,至于前后匹配多少字符你们自行修改,但也是处于不太好用的状态,毕竟是分片还是有点奇怪,对英文来说应该是单词识别,只是中文恰巧是另一标准,单字变成了词

#:~:text=勿滥用-,表情,-符号和

CDN:
# search
algolia_js: https://cdn.jsdelivr.net/gh/CCKNBC/ccknbc.github.io/js/search/algolia.js
window.addEventListener("load", () => {
const openSearch = () => {
const bodyStyle = document.body.style;
bodyStyle.width = "100%";
bodyStyle.overflow = "hidden";
btf.animateIn(document.getElementById("search-mask"), "to_show 0.5s");
btf.animateIn(
document.querySelector("#algolia-search .search-dialog"),
"titleScale 0.5s"
);
setTimeout(() => {
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
}, 100);

// shortcut: ESC
document.addEventListener("keydown", function f(event) {
if (event.code === "Escape") {
closeSearch();
document.removeEventListener("keydown", f);
}
});
};

const closeSearch = () => {
const bodyStyle = document.body.style;
bodyStyle.width = "";
bodyStyle.overflow = "";
btf.animateOut(
document.querySelector("#algolia-search .search-dialog"),
"search_close .5s"
);
btf.animateOut(document.getElementById("search-mask"), "to_hide 0.5s");
};

const searchClickFn = () => {
document
.querySelector("#search-button > .search")
.addEventListener("click", openSearch);
};

const searchClickFnOnce = () => {
document
.getElementById("search-mask")
.addEventListener("click", closeSearch);
document
.querySelector("#algolia-search .search-close-button")
.addEventListener("click", closeSearch);
};

const algolia = GLOBAL_CONFIG.algolia;
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName;
if (!isAlgoliaValid) {
return console.error("Algolia setting is invalid!");
}

const search = instantsearch({
indexName: algolia.indexName,
searchClient: algoliasearch(algolia.appId, algolia.apiKey),
searchFunction(helper) {
helper.state.query && helper.search();
},
});

const configure = instantsearch.widgets.configure({
hitsPerPage: algolia.per_page || 5,
});

const searchBox = instantsearch.widgets.searchBox({
container: "#algolia-search-input",
showReset: false,
showSubmit: false,
searchAsYouType: false,
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
showLoadingIndicator: true,
});

const hits = instantsearch.widgets.hits({
container: "#algolia-hits",
templates: {
item(data) {
const link = data.permalink
? data.permalink
: GLOBAL_CONFIG.root + data.path;
const content = data._snippetResult.contentStrip.value;
return `
<a href="${link}#:~:text=${content.substring(
content.indexOf("<mark>") - 3,
content.indexOf("<mark>")
)}-,${content.substring(
content.indexOf("<mark>") + 6,
content.indexOf("</mark>")
)},-${content.substring(
content.indexOf("</mark>") + 7,
content.indexOf("</mark>") + 10
)}" class="algolia-hit-item-link">
<b>${data._highlightResult.title.value || "no-title"}</b>
<br>${content}</br>
匹配字词: <em><mark>${
data._highlightResult.contentStrip.matchedWords
}</mark></em> | 匹配等级: <em><mark>${
data._highlightResult.contentStrip.matchLevel
}</mark></em>
</a>`;
},
empty: function (data) {
return (
'<div id="algolia-hits-empty">' +
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(
/\$\{query}/,
data.query
) +
"</div>"
);
},
},
});

const stats = instantsearch.widgets.stats({
container: "#algolia-info > .algolia-stats",
templates: {
text: function (data) {
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
.replace(/\$\{hits}/, data.nbHits)
.replace(/\$\{time}/, data.processingTimeMS);
return `<hr>${stats}`;
},
},
});

const powerBy = instantsearch.widgets.poweredBy({
container: "#algolia-info > .algolia-poweredBy",
});

const pagination = instantsearch.widgets.pagination({
container: "#algolia-pagination",
totalPages: algolia.totalPages,
templates: {
first: '<i class="fa-solid fa-angle-double-left" title="第一页"></i>',
last: '<i class="fa-solid fa-angle-double-right" title="最后一页"></i>',
previous: '<i class="fa-solid fa-angle-left" title="上一页"></i>',
next: '<i class="fa-solid fa-angle-right" title="下一页"></i>',
},
});

search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]); // add the widgets to the instantsearch instance

search.start();

searchClickFn();
searchClickFnOnce();

window.addEventListener("pjax:complete", () => {
getComputedStyle(document.querySelector("#algolia-search .search-dialog"))
.display === "block" && closeSearch();
searchClickFn();
});

window.pjax &&
search.on("render", () => {
window.pjax.refresh(document.getElementById("algolia-hits"));
});
});

效果预览

(这个是因为我修改了源码,实际上也能通过修改 JS 实现,但大多数人不会关心这些搜索小贴士)对于中文它当作单字匹配允许拼写错误

特别说明

因两个月前已申请通过,本博客已切换至不限搜索次数的DocSearch!同时也加入了开源计划,但因为 10DSN 太香了,虽然 instantsearch 可玩性更好,但我也只申请了 200k/月的额度(虽然可以增加),所以为了即时搜索我还是选择了白嫖,而且设定为每天自动爬取的话,省去了生成索引上传的这一步骤,节省了自动部署的时间。而且爬取到数据后,前端我并非一定要使用 docsearch 方案,用 instantsearch 配合其他插件也不是不可以。

]]>
本文介绍了 Hexo Butterfly 主题下 Algolia 搜索的使用https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/#post-comment
你的公共电视https://blog.ccknbc.cc/posts/about-pts/2022-08-07T05:16:00.000Z2022-10-16T14:06:00.000Z查看本文语雀版本【首发】,自动同步更新至CC 的部落格

作为一个大陆人,时常希望有一个独立于官媒的非自媒体存在,你可能会提到傲娇的“六公主”;而这次,我想和大家聊一聊这个台湾媒体中特别的存在【公共电视】

关于公视

公视使命

“公共电视”是一种电视制度, 在传播学理上有其定义与任务。

它必须有自己的频道、 自己的电台、 有自己的节目政策, 所有的播出都是为了服务公众, 提供公众必须的资讯为主要功能。

因此, 公视和宣导政令的国家电视不同, 和以广告、收视率好坏来取决节目内容的商业电视不同。

公视属于全体民众, 不专为政府或某一政党服务; 不以营利为目的, 也不受商业或利益团体左右, 公共电视,顾名思义, 是接收全民付託, 以服务公共利益为宗旨的电视媒体。

那【公视】与 【台视】【华视】【民视】【中视】等带有明显倾向色彩的电视台有什么不同呢?台湾虽然本土面积不大,但却拥有者 300 多家电视台,在这里开电视台,真的就是靠财团砸钱。你或许知道【中视】与【中天】的老板是同一个,没错就是“旺旺”,因此你可以经常看到记者手持两家电视台的麦克风,一条新闻两台播,这样比较省钱啦,而因为具有明显的亲中色彩,两家在岛内的收视率或许并没有那么高,【中天新闻台】也只是被迫改为网络播出。

台湾公广集团有:公共电视,PTS Taiwan (English),公视台语台,中华电视公司,客家电视台

那你也就可以理解为什么【公视】经常称呼【华视】为友台,一开始我们有提到过,它并不在乎自己的收视率,因此不论你何时切到公视,都是没有广告的,这与其他频道是一个明显的区别;那上面提到过运营一家电视台真的很烧钱,公视为什么每年还有那么多自制剧,资金链从哪来?

经费来源

世界上其他国家也有公共媒体,不同于 NHK, BBC,公民需要每年像这些公共媒体强制性缴纳费用,公视经费主要来源有以下

  1. 公视基金会第一年得到的政府捐赠 为十二亿元新台币, 自筹款为三亿元。依据公共电视法, 政府捐赠的金额逐年递减百分之十, 至第六年以后应为第一年政府编列预算 金额的百分之五十, 因此公视自筹款负担将逐年大幅增加, 对一个肩负使命的非营利电视台而言, 无疑是一个高难度的挑战。为避免过于倚赖政府捐赠, 以增加公视财务独立性,在作法上有:

  2. 企业赞助:由公、私立机构或企业团体提供经费,赞助播出之时段或节目。“企业赞助”不同于一般广告赞助,受限于电视台的基本规范,不得促销特定商品或服务、不与节目题材有任何关联或暗示、不参与任何节目制播过程等,因此能够独立自主, 避免伴随经费而来的干预。公视节目品质精緻、立意良善, 受到许多公、私立机构、企业予以肯定,并提供经费赞助, 成为公视制作精緻节目的重要支柱。

  3. 个人捐赠:成立“公视之友”会员制度,希望汇集来自民间的力量,成为公共电视在民间的重要基础。“公视之友”认同本会理念 并以捐款的方式赞助公视,公视除制作精良的节目外, 以《公视之友》月刊做为与“公视之友”沟通的桥樑,此外亦提供“公视之友”适当的回馈,如购买本会相关产品享有折扣优惠、不定期举办专题讲座等。同时, 举办文化、教育、残障等公益活动时,邀请“公视之友”担任志工, 让公共电视提倡的理念落实到生活中。

  4. 其它财源:公视拥有各类型精緻的节目为基础,利于开发各项公共电视文化事业活动,如促销与节目相关之录影带、 图书资料、教材及副产品等, 将节目资源再利用,延伸节目的制作价值。此外, 公视摄影棚、剪辑、音效等设备,在法规允许的范围内,行有馀力时, 予以出租,供其它传播公司、大学相关科系 付费使用,以合理的租金做为硬体维护费用。公视开播以来, 积极争取企业赞助,并以节目行销、 设备出租的方式获取经费; 公共电视更透过一步一脚印的 地方巡迴服务、 各项媒体的宣传及社会大众的推荐,使“公视之友”人数迅速成长,这正代表公视的理念与品质受到肯定, 成为公视往前迈进的最大动力。

算下来,台湾人每年向公视提供 35 新台币的支持,因此每位台湾人都是公视的“干爸/干妈”

中国台湾公共電視台
英國公共電視台
美國公共電視台
日本 NHK 公共電視台
法國公共電視台 Francetv.fr
法國公共電視台 ARTE
法國公共電視台 法國法蘭西 24
加拿大公共電視台
澳洲公共電視台
德國公共電視台
澳洲公共電視台(SBS)
丹麥公共電視台
西班牙公共電視台
挪威公共電視台
瑞典公共電視台
芬蘭公共電視台

创办历史

公视建台历史

1980年

当时的行政院长孙运璿先生提出公共电视台的主张。他说,今天不做,明天会后悔。

1983年

新闻局提出公视节目制作中心计划草案,但因经费过高、人力庞大而搁置。

1984年

新闻局设立公共电视制播小组,向三家无线电视台徵用时段播出。

1986年

公共电视节目制作的任务,转由财团法人广电基金下设的公共电视节目制播组负责, 广电基金所制作的节目,仍然没有专属频道播出,在三台借用的时段经常被调动,影响观众收视权益。

1991年

行政院核定公共电视台筹备委员会设置点,公视筹委会正式运作。公视筹委会委託七位学者专家组成公共电视法草案立法小组,并经过缜密的研议,提出公共电视法草案。

1993年

行政院将公共电视法送交立法院审查。

1996年9月

一群关心公共电视的学术文化界人士 ,组成公共媒体催生联盟,结合各界支持公共电视的力量, 以促使公视法通过。

1997年5月31日

经由民间锲而不捨的游说及 立法院密集的政党协商, 公视法惊险过关,完成三读。

1998年1月

第一届公共电视董监事十八位人选经立法院推举的提名审查委员会审议通过。三月,董监事召开第一次会议,选出吴丰山先生为董事长, 贺德芬女士为常务监事。

1998年7月1日

财团法人公共电视文化事业基金会 正式成立,公共电视台并于同日开播,完成长达十八年的建台历程。

公视的未来有很长的路要走, 许多困难与险阻有待我们一一克服,而您正站在公视成长的时间轴上,见证改造省内媒体环境的长期奋战, 公视盼与您携手,共同为打造媒体的美丽新“视”界努力!

公视已在 2018 年走过了 20 个年头,而“看见更好的未来”是时代赋予它的新使命,此外公视还是全台第一家试验 4K 播出的电视台

制播理念

以多元的视野、多样的风貌和 高品质的专业制作来服务公众, 促进教育文化发展, 是全世界公共电视节目共同的特色, 也是公视奋力追求的目标。在节目规划上,公视秉持以下九大理念:

  1. 真心关爱儿童的成长
  2. 尊重各族群的需求
  3. 关怀弱势团体与文化
  4. 呈现表演艺术的生命力
  5. 重视台湾生态保育
  6. 纪录台湾社会变迁及人文风貌
  7. 亲近民众的生活
  8. 展现文学之美
  9. 掌握社会脉动、开拓国际视野

公视节目不以单一节目吸引大量观众, 而是透过整体节目表的安排,由多元样貌的节目来满足不同族群, 或不同爱好者的特殊需求。为了向民众提供 有别于商业逻辑的更佳选择, 公视的节目制作涵盖下列目标:提供全民终身学习的管道。增进人民对新闻事件和公共事务的瞭解,善尽媒体监督政府的第四权责任。提供重要议题和观念的分析和解释。提供人民对台湾和他国丰富文化、 历史的认知, 并培养本土关怀和国际视野。增进国际社会对台湾风土人情的瞭解。使人民接触多元的表演艺术。提供各种社会团体如少数民族、弱势团体,公平参与的机会与表达艺术和政治上的意见空间。播映和典藏重要的影视经典作品。

因为有《公共电视法》的庇护,公视在这些年里是有制播许多优秀节目的,这里不再一一列出,光是看“广播电视金钟奖”入围获奖名单都可以知道。

公开透明

这是公共媒体一个显著的特征,因为这个媒体是属于人民,服务人民的,并受到人们监督。所有相关信息,均可在官网查询到,不过仍然要遵循 CC 创用规则哦。

频道

公视主频是台湾的公共电视媒体——公共电视台(公视)的主频道,一般称呼为“公共电视”或简称为“公视”(部分节目预告片尾将本频道称呼为“公视频道”)。内容为综合台形式,特色是比其他无线台(台视、中视、华视、民视)更重视公共服务节目及弱势族群(儿童、老人、原住民族等)节目。中央气象局发布海上台风警报期间,公视主频道会在每整点前数分钟固定录影转播中央气象局台风动态说明会,也会在画面左侧开启滚动字幕报导台风最新动态及台风警报范围。公视的台标在节目播完后会由半透明变成“彩色”。2012 年 6 月 30 日中午起,无线电视数字化后定频于 26 频道。2016 年 6 月 8 日,NCC 通过公视换照和营运计划变更案;自 7 月 6 日起升级 HD 讯号播出,和客家电视台、原住民族电视台并列第四个主频道升级为高清讯号的电视台。2020 年 6 月 1 日,公视主频改为 24 小时全日播出,收播时间改为每月第 1 个周四 02:00~06:00。公视台语台(台湾话:Kong-sī Tâi-gí-tâi)是台湾公共电视台旗下的电视频道之一,前身为 2004 年 7 月 1 日开播的“Dimo TV”、以及 2012 年 10 月 1 日更名的“公视 2 台”,2019 年 7 月 1 日改为现名,为台湾第一个以全台语播出的公共性电视频道。公视 3 台是公共电视文化事业基金会旗下的一个电视频道,也是台湾第一个高清电视频道。由公视接受行政院新闻局“公共广电与文化创意、数字电视发展两年计划”补助建置经营。2008 年 5 月 15 日睌上 8 点起开始试播,第一个播出的节目为连续剧《美味关系》。2012 年 7 月 24 日正式开播,节目内容则以外国电影、戏曲、文化艺术和体育赛事等为主。创台之初的频道名称为“HiHD”,“Hi”是“招呼”、“迎接”之意,“HD”是“High Definition”(高清)之意。2012 年 8 月 31 日起,频道名称由“HiHD”更改为“公视 HD”。2016 年 7 月 6 日凌晨两点起更名为“公视 3 台”,定位为体育赛事、艺文、各国剧集的频道。

Taiwan+

为什么要把Taiwan+分离出来说,是因为TaiwanPlus开播于今年 10 月 3 日,而他的开台历程与公视有着密不可分的关系。

Taiwan+(中文:台湾+),又称TaiwanPlus,为影音串流平台。由台湾省文化部设立、中央通讯社主责执行的“国际影音串流平台计划”,正式定名为“TaiwanPlus”,是台湾首个向国际观众宣扬台湾的英语影音新闻和节目的平台,平台于 2021 年 8 月 30 日正式上线。2022 年 6 月 9 日,平台由公共电视文化事业基金会经营,并于 10 月 3 日开播电视频道。

中央社称,TaiwanPlus 是台湾有史以来最大的台湾视讯平台,目的是将台湾的节目、新闻和故事带到全世界,内容设定包括严肃的新闻议题、软性的文化及艺术主题。TaiwanPlus 旨在发出台湾的声音,向英语世界提供区域事件和问题的多媒体报导。 路透社则报导,TaiwanPlus 成立时,正值中国大陆积极透过英语媒界,尤其是透过中国环球电视网(CGTN),向外界传播其观点,并同时在打压台湾的国际空间。

TaiwanPlus建台历史

2020年7月

台湾省文化部便开始委托公视建置英语网络影音平台,规划国际数位传播发展计划,向世界宣告台湾的经验与价值。这个名叫“国际传播数位计划”的前导计划耗资 10 亿元新台币,原计划 2021 年上线,涵盖新闻、节目、专题、纪录片等内容。外界普遍质疑该计划会令公视成为类似于我们大陆的“大外宣”机构,而公视董事冯小非曾一度于 Facebook 贴文抨击执政当局介入公视经营,罔顾公视独立性,就连公视高层也没守住应守防线。多位董事表达不满之下,公视于 7 月 27 日举行临时董事会,最终以 11 票对 4 票通过影音平台计划,时任公视总经理曹文杰、执行副总经理谢翠玉、新闻部经理苏启祯当场辞职抗议。最终,文化部于 29 日宣布终止有关“国际影音平台”委托案,但会另寻执行方式,力争次年 1 月 1 日开播。

2021年5月

该计划最终由中央社承接,正式定名为“TaiwanPlus”由福斯传媒集团亚洲区执行副总裁暨大中华区董事总经理蔡秋安担任执行长。

2021年8月30日

TaiwanPlus 影音串流平台正式上线时,也将由台湾戏剧“斯卡罗”打头阵,同步抢先在海外地区独家首播。

2022年6月9日

TaiwanPlus 与中央社合约到期后,由公视经营。

2022年8月17日

NCC 核准公视新增“TaiwanPlus”服务,以传统的电视频道形式开播,同时于其他电视平台上架,9 月 8 日起于无线数位频号 CH7 进行频道讯号测试,预计于 10 月 3 日开播。

2022年9月14日

中华电信 MOD 新增“TaiwanPlus”频道,于 10 月 3 日免订阅上架。定频于 558 台。

2022年10月3日

正式开台。

台湾省民众最不能接受的是,参与 Taiwan Plus 平台视觉识别系统设计的 JL Design 公司,同样也接了我们的官方媒体中国中央电视台旗下中国中央电视台纪录频道中国环球电视网纪录频道的频道包装设计。2022 年 2 月,外媒驻台记者 Sam Reynolds 发现,TaiwanPlus 影音平台流量少得可怜,实在未能达到“宣扬台湾”效果。民众党对此批评,该平台无助于把台湾特色行销到世界。Taiwan Plus 软开台(Soft launch)一年后,Taiwan Plus App 下载约十二万次,相较当初设定百万人次,达成率仅一成多,引起国民党立委万美玲质疑。国民党立委林奕华郑正钤亦抨击,TaiwanPlus 的电视频道没有法源依据,“都是政府主导,要什么就要什么,没法源就要硬干”。

我的观点

时至今日,如果站在台湾的角度看问题,公视真的做到了它该做的吗?

答案是确实做到了,从历年来制播表现与获奖记录,公视人为台湾电视留下了很多优秀的节目

我记得前两年,在台语台开台的时候,对 2003 年的戏剧《后山日先照》做了修复,张美瑶确实让我为之流泪;这样的例子很多,《一把青》,《你的孩子不是你的孩子》,《我们与恶的距离》,《生死接线员》,《噬罪者》等优秀的电视剧;《公视电影院,《公视人生剧展》,《学生剧展》,《新创电影》,《听听看》,《有话好说》等一系列节目均出自公视,他会给很多新人机会,也造就了经典,“水果奶奶”应该是许多人的回忆。

另外公视的频道包装也是很好看的,算是很有风格的 ID

如果不被政党介入,那么也就不会有“公视门”事件?

这个东西很难讲,我一个没参加过什么选举的人也不太好说,但有一点,公视确实会受执政党影响,而公视董事会是否能坚持住底线,又或者说公视法能不能保护公视不被外部势力侵入这个需要进一步观察。

如果它绿了,它真的还算中立吗?

从各个节目来看,台湾媒体一直是开放自由的状态,不论你是何种立场,均可以畅所欲言,允许不同的声音才有进步

而你看公视新闻会与其他台会感觉有明显差异,首先英语,越南语,泰语,台语,手语等新闻的播出是一种创新的国际化尝试,新闻内容也不局限于鸡毛蒜皮的小事,主播在播报时也不太会有个人立场的介入,因此算得上中规中矩。

大陆是否有会有全国性的公共媒体?

我觉得不太好说,至少目前这个阶段我觉得先把节目分级制度搞定比较重要,不要一刀切,允许更多的创作自由才有更多优秀的作品。我一直相信我们大陆的电影,电视或者综艺都可以做的更好,只是目前限制条件过多受到影响较大。


最后,希望两岸早日完成和平统一,落叶归根!

]]>
作为一个大陆人,时常希望有一个独立于官媒的非自媒体存在,而这次,我想和大家聊一聊这个台湾媒体中特别的存在【公共电视】https://blog.ccknbc.cc/posts/about-pts/#post-comment
\ No newline at end of file diff --git a/baidusitemap.xml b/baidusitemap.xml new file mode 100644 index 000000000..43ffe6bb8 --- /dev/null +++ b/baidusitemap.xml @@ -0,0 +1 @@ +https://blog.ccknbc.cc/posts/the-real-addthis/2023-06-25https://blog.ccknbc.cc/posts/hexo-webpushr-notification/2023-06-25https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/2023-03-12https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/2023-02-16https://blog.ccknbc.cc/posts/about-pts/2022-10-16https://blog.ccknbc.cc/posts/yuque-to-hexo/2022-10-04https://blog.ccknbc.cc/posts/how-to-hide-hexo-articles-gracefully/2022-09-18https://blog.ccknbc.cc/posts/ccs-work-diary-part3/2022-06-14https://blog.ccknbc.cc/posts/ccs-work-diary-part2/2021-12-02https://blog.ccknbc.cc/posts/2fa-last-security-line/2021-12-01https://blog.ccknbc.cc/posts/google-adsense-configuration-manual/2021-11-08https://blog.ccknbc.cc/posts/56th-golden-bell-awards/2021-10-13https://blog.ccknbc.cc/posts/waline-comments-system-deployment-logs/2021-09-28https://blog.ccknbc.cc/posts/ccs-work-diary-part1/2021-08-28https://blog.ccknbc.cc/posts/ta-said-nothing/2021-07-20https://blog.ccknbc.cc/posts/implementation-of-simple-browser-update-push/2021-05-18https://blog.ccknbc.cc/posts/awesome-status-pages/2021-05-18https://blog.ccknbc.cc/posts/introduction-of-plugin-tags-based-on-butterfly/2021-05-16https://blog.ccknbc.cc/posts/add-email-subscription-to-your-hexo-blog/2021-05-15https://blog.ccknbc.cc/posts/cusdis-or-disqus/2021-05-12https://blog.ccknbc.cc/posts/github-automatically-merges-pull-requests-notes/2021-01-17https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/2021-01-11https://blog.ccknbc.cc/posts/research-on-image-denoising-technology-based-on-wavelet-transform/2021-01-10https://blog.ccknbc.cc/posts/how-to-ask-questions-the-smart-way/2020-12-30https://blog.ccknbc.cc/posts/special-test-article/2020-12-27https://blog.ccknbc.cc/posts/the-webp-road-of-blog-pictures/2020-12-15https://blog.ccknbc.cc/posts/i-dont-really-want-html/2020-11-26https://blog.ccknbc.cc/posts/playlist-conversion-of-major-music-platforms/2020-11-14https://blog.ccknbc.cc/posts/how-to-enjoy-joox-music-service-in-mainland-china/2020-11-10https://blog.ccknbc.cc/posts/course-design/2020-11-03https://blog.ccknbc.cc/posts/why-github-actions-is-so-popular/2020-10-06https://blog.ccknbc.cc/posts/why-did-i-choose-tidio-as-the-chat-system/2020-10-03https://blog.ccknbc.cc/posts/about-the-55th-golden-bell-awards/2020-09-26https://blog.ccknbc.cc/posts/resume-template/2020-09-13https://blog.ccknbc.cc/posts/uptime-free-website-survival-monitoring/2020-08-20https://blog.ccknbc.cc/posts/hexo-toss/2020-07-01https://blog.ccknbc.cc/posts/production-practice/2020-06-29https://blog.ccknbc.cc/posts/digital-watermark-detection-based-on-wavelet-transform/2020-06-09 \ No newline at end of file diff --git a/blogroll/index.html b/blogroll/index.html new file mode 100644 index 000000000..e7c26cf7a --- /dev/null +++ b/blogroll/index.html @@ -0,0 +1,19 @@ +CC的小伙伴们 | CC的部落格

CC的小伙伴们


评论
\ No newline at end of file diff --git a/brokenlinks.txt b/brokenlinks.txt new file mode 100644 index 000000000..e69de29bb diff --git a/categories/index.html b/categories/index.html new file mode 100644 index 000000000..474882e73 --- /dev/null +++ b/categories/index.html @@ -0,0 +1,19 @@ +文章分类 | CC的部落格
\ No newline at end of file diff --git "a/categories/\345\215\232\345\256\242/index.html" "b/categories/\345\215\232\345\256\242/index.html" new file mode 100644 index 000000000..8c1796e49 --- /dev/null +++ "b/categories/\345\215\232\345\256\242/index.html" @@ -0,0 +1,19 @@ +分类: 博客 | CC的部落格
\ No newline at end of file diff --git "a/categories/\345\217\260\346\271\276/index.html" "b/categories/\345\217\260\346\271\276/index.html" new file mode 100644 index 000000000..a5b067bfe --- /dev/null +++ "b/categories/\345\217\260\346\271\276/index.html" @@ -0,0 +1,19 @@ +分类: 台湾 | CC的部落格
分类 - 台湾
2022
你的公共电视
你的公共电视
2021
第56届电视金钟奖
第56届电视金钟奖
2020
第55届金钟奖相关
第55届金钟奖相关
\ No newline at end of file diff --git "a/categories/\345\255\246\344\271\240/index.html" "b/categories/\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..57b3cb4fe --- /dev/null +++ "b/categories/\345\255\246\344\271\240/index.html" @@ -0,0 +1,19 @@ +分类: 学习 | CC的部落格
\ No newline at end of file diff --git "a/categories/\345\267\245\344\275\234/index.html" "b/categories/\345\267\245\344\275\234/index.html" new file mode 100644 index 000000000..a2d03b528 --- /dev/null +++ "b/categories/\345\267\245\344\275\234/index.html" @@ -0,0 +1,19 @@ +分类: 工作 | CC的部落格
分类 - 工作
2022
CC的社畜日记 Part3
CC的社畜日记 Part3
2021
CC的社畜日记 Part2
CC的社畜日记 Part2
CC的社畜日记 Part1
CC的社畜日记 Part1
2020
简历模板
简历模板
\ No newline at end of file diff --git "a/categories/\345\267\245\345\205\267/index.html" "b/categories/\345\267\245\345\205\267/index.html" new file mode 100644 index 000000000..3a7c286cd --- /dev/null +++ "b/categories/\345\267\245\345\205\267/index.html" @@ -0,0 +1,19 @@ +分类: 工具 | CC的部落格
\ No newline at end of file diff --git "a/categories/\347\224\237\346\264\273/index.html" "b/categories/\347\224\237\346\264\273/index.html" new file mode 100644 index 000000000..bb8903fc8 --- /dev/null +++ "b/categories/\347\224\237\346\264\273/index.html" @@ -0,0 +1,19 @@ +分类: 生活 | CC的部落格
分类 - 生活
2021
Ta 什么都不说
Ta 什么都不说
\ No newline at end of file diff --git "a/categories/\351\237\263\344\271\220/index.html" "b/categories/\351\237\263\344\271\220/index.html" new file mode 100644 index 000000000..04544d553 --- /dev/null +++ "b/categories/\351\237\263\344\271\220/index.html" @@ -0,0 +1,19 @@ +分类: 音乐 | CC的部落格
\ No newline at end of file diff --git a/css/custom.css b/css/custom.css new file mode 100644 index 000000000..96d49a566 --- /dev/null +++ b/css/custom.css @@ -0,0 +1 @@ +@-webkit-keyframes ccc{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}@keyframes ccc{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}#article-container.post-content h2::before{content:'H₂'}#article-container.post-content h3::before{content:'H₃'}#article-container.post-content h4::before{content:'H₄'}#article-container.post-content h5::before{content:'H₅'}#article-container.post-content h6::before{content:'H₆'}.promptglowingcircle,.webpushr-bell-theme-dark prompticon3{z-index:auto;background:var(--btn-bg)}.promptglowingcircle,[data-theme=dark] .webpushr-bell-theme-dark prompticon3{background:var(--btn-bg)}[data-theme=dark] .promptglowingcircle{border:1px solid #fffFFFB3}:root{--docsearch-primary-color:#8fbc8f!important;--docsearch-logo-color:#8fbc8f!important}[data-theme=dark]{--docsearch-primary-color:#5468ff!important;--docsearch-logo-color:#5468ff!important}.DocSearch-Logo .cls-1,.DocSearch-Logo .cls-2{fill:var(--docsearch-logo-color)!important}@media (max-width:768px){#card-qrcode{display:none}}#card-qrcode{background:var(--card-bg)!important;padding:15px 0;height:118px;-moz-user-select:none;-khtml-user-select:none;user-select:none}#card-qrcode #tj-box{width:100%;height:100%;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;transition:.4s cubic-bezier(0, 0, 0, 1.29)}#card-qrcode #tj-box2{transform:rotateY(180deg);-webkit-transform:rotateY(180deg)}#card-qrcode #tj-box1,#card-qrcode #tj-box2{display:flex;justify-content:center;flex-wrap:nowrap;position:absolute;height:100%;width:100%;backface-visibility:hidden;-webkit-backface-visibility:hidden}#card-qrcode #tj-img-box{border-radius:12px;margin-left:10px;height:85px}#card-qrcode #tj-img-box img{height:85px;border-radius:12px;filter:brightness(.95)}[data-theme=dark] #card-qrcode #tj-img-box img,[data-theme=dark] #card-qrcode #tj-left{filter:brightness(.6)}#card-qrcode #tj-left{color:var(--toc-link-color);filter:brightness(.95);height:85px}#card-qrcode #tj-left p{margin:10px 0 0;font-size:32px;line-height:normal;font-weight:800}#card-qrcode #tj-left span{font-size:15px;font-weight:800}#card-qrcode:hover #tj-box{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}#card-info-btn,#rightside>div>button,#to_comment,.edit-github,.edit-gitlab,.edit-gitlab-ide,.edit-yuque{border-radius:90px!important} \ No newline at end of file diff --git a/css/index.css b/css/index.css new file mode 100644 index 000000000..b49c248fe --- /dev/null +++ b/css/index.css @@ -0,0 +1 @@ +@-webkit-keyframes ccc{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}@keyframes ccc{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}#article-container.post-content h2::before{content:'H₂'}#article-container.post-content h3::before{content:'H₃'}#article-container.post-content h4::before{content:'H₄'}#article-container.post-content h5::before{content:'H₅'}#article-container.post-content h6::before{content:'H₆'}.promptglowingcircle,.webpushr-bell-theme-dark prompticon3{z-index:auto;background:var(--btn-bg)}.promptglowingcircle,[data-theme=dark] .webpushr-bell-theme-dark prompticon3{background:var(--btn-bg)}[data-theme=dark] .promptglowingcircle{border:1px solid #fffFFFB3}.DocSearch-Logo .cls-1,.DocSearch-Logo .cls-2{fill:var(--docsearch-logo-color)!important}@media (max-width:768px){#card-qrcode{display:none}}#card-qrcode{background:var(--card-bg)!important;padding:15px 0;height:118px;-moz-user-select:none;-khtml-user-select:none;user-select:none}#card-qrcode #tj-box{width:100%;height:100%;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;transition:.4s cubic-bezier(0, 0, 0, 1.29)}#card-qrcode #tj-box2{transform:rotateY(180deg);-webkit-transform:rotateY(180deg)}#card-qrcode #tj-box1,#card-qrcode #tj-box2{display:flex;justify-content:center;flex-wrap:nowrap;position:absolute;height:100%;width:100%;backface-visibility:hidden;-webkit-backface-visibility:hidden}#card-qrcode #tj-img-box{border-radius:12px;margin-left:10px;height:85px}#card-qrcode #tj-img-box img{height:85px;border-radius:12px;filter:brightness(.95)}[data-theme=dark] #card-qrcode #tj-img-box img,[data-theme=dark] #card-qrcode #tj-left{filter:brightness(.6)}#card-qrcode #tj-left{color:var(--toc-link-color);filter:brightness(.95);height:85px}#card-qrcode #tj-left p{margin:10px 0 0;font-size:32px;line-height:normal;font-weight:800}#card-qrcode #tj-left span{font-size:15px;font-weight:800}#card-qrcode:hover #tj-box{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}#card-info-btn,#rightside>div>button,#to_comment,.edit-github,.edit-gitlab,.edit-gitlab-ide,.edit-yuque{border-radius:90px!important}/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}details,main{display:block}h1{font-size:2em}hr{box-sizing:content-box;height:0;overflow:visible}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}#article-container .flink .flink-item-desc,#article-container .flink .flink-item-name,#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a span,#aside-content .card-categories ul.card-category-list>.card-category-list-item a span,#nav #blog-info,#pagination .next_info,#pagination .prev_info,#sidebar #sidebar-menus .menus_items .site-page,.limit-one-line,.site-data>a .headline{overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap}#article-container figure.gallery-group .gallery-group-name,#article-container figure.gallery-group p,#aside-content .aside-list>.aside-list-item .content>.comment,#aside-content .aside-list>.aside-list-item .content>.name,#aside-content .aside-list>.aside-list-item .content>.title,#post-info .post-title,#recent-posts>.recent-post-item>.recent-post-info>.article-title,#recent-posts>.recent-post-item>.recent-post-info>.content,.article-sort-item-title,.error404 #error-wrap .error-content .error-info .error_subtitle,.limit-more-line,.relatedPosts>.relatedPosts-list .content .title{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}#article-container a.headerlink:after,#article-container h1:before,#article-container h2:before,#article-container h3:before,#article-container h4:before,#article-container h5:before,#article-container h6:before,#post .post-copyright:before,#post .post-outdate-notice:before,.fontawesomeIcon,.note:not(.no-icon)::before{display:inline-block;font-weight:600;font-family:'Font Awesome 6 Free';text-rendering:auto;-webkit-font-smoothing:antialiased}#aside-content .card-widget,#recent-posts>.recent-post-item,.cardHover,.error404 #error-wrap .error-content,.layout>.recent-posts .pagination>:not(.space),.layout>div:first-child:not(.recent-posts){border-radius:8px;background:var(--card-bg);-webkit-box-shadow:var(--card-box-shadow);box-shadow:var(--card-box-shadow);-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}#aside-content .card-widget:hover,#recent-posts>.recent-post-item:hover,.cardHover:hover,.error404 #error-wrap .error-content:hover,.layout>.recent-posts .pagination>:not(.space):hover,.layout>div:first-child:not(.recent-posts):hover{-webkit-box-shadow:var(--card-hover-box-shadow);box-shadow:var(--card-hover-box-shadow)}#aside-content .aside-list>.aside-list-item .thumbnail :first-child,#recent-posts>.recent-post-item .post_cover .post-bg,.article-sort-item-img :first-child,.error404 #error-wrap .error-content .error-img img,.imgHover{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .6s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .6s;-o-transition:filter 375ms ease-in .2s,-o-transform .6s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .6s;transition:filter 375ms ease-in .2s,transform .6s;object-fit:cover}#aside-content .aside-list>.aside-list-item .thumbnail :first-child:hover,#recent-posts>.recent-post-item .post_cover .post-bg:hover,.article-sort-item-img :first-child:hover,.error404 #error-wrap .error-content .error-img img:hover,.imgHover:hover{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#pagination .next-post:hover .cover,#pagination .prev-post:hover .cover,.postImgHover:hover .cover,.relatedPosts>.relatedPosts-list>div:hover .cover{opacity:.8;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#pagination .next-post .cover,#pagination .prev-post .cover,.postImgHover .cover,.relatedPosts>.relatedPosts-list>div .cover{position:absolute;width:100%;height:100%;opacity:.4;-webkit-transition:.6s,filter 375ms ease-in .2s;-moz-transition:.6s,filter 375ms ease-in .2s;-o-transition:.6s,filter 375ms ease-in .2s;-ms-transition:.6s,filter 375ms ease-in .2s;transition:.6s,filter 375ms ease-in .2s;object-fit:cover}.category-lists ul,.list-beauty{list-style:none}.category-lists ul li,.list-beauty li{position:relative;padding:.12em .4em .12em 1.4em}.category-lists ul li:hover:before,.list-beauty li:hover:before{border-color:var(--pseudo-hover)}.category-lists ul li:before,.list-beauty li:before{position:absolute;top:.67em;left:0;width:.43em;height:.43em;border:.215em solid #8fbc8f;border-radius:.43em;background:0 0;content:'';cursor:pointer;-webkit-transition:.3s ease-out;-moz-transition:.3s ease-out;-o-transition:.3s ease-out;-ms-transition:.3s ease-out;transition:.3s ease-out}#article-container hr,.custom-hr,.search-dialog hr{position:relative;margin:40px auto;border:2px dashed var(--hr-border)}.scroll-down-effects{-webkit-animation:1.5s infinite scroll-down-effect;-moz-animation:1.5s infinite scroll-down-effect;-o-animation:1.5s infinite scroll-down-effect;-ms-animation:scroll-down-effect 1.5s infinite;animation:1.5s infinite scroll-down-effect}.reward-main{-webkit-animation:.3s .1s both donate_effcet;-moz-animation:.3s .1s both donate_effcet;-o-animation:.3s .1s both donate_effcet;-ms-animation:donate_effcet 0.3s 0.1s ease both;animation:.3s .1s both donate_effcet}@-moz-keyframes scroll-down-effect{0%,100%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}}@-webkit-keyframes scroll-down-effect{0%,100%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}}@-o-keyframes scroll-down-effect{0%,100%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}}@keyframes scroll-down-effect{0%,100%{top:0;opacity:.4}50%{top:-16px;opacity:1;-ms-filter:none;filter:none}}@-moz-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes header-effect{0%{opacity:0;-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes headerNoOpacity{0%{-webkit-transform:translateY(-50px);-moz-transform:translateY(-50px);-o-transform:translateY(-50px);-ms-transform:translateY(-50px);transform:translateY(-50px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-webkit-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-o-keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@keyframes bottom-top{0%{margin-top:50px;opacity:0}100%{margin-top:0;opacity:1;-ms-filter:none;filter:none}}@-moz-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-webkit-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-o-keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@keyframes titleScale{0%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-moz-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-webkit-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-o-keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@keyframes search_close{0%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-moz-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-webkit-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-o-keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@keyframes to_show{0%{opacity:0}100%{opacity:1;-ms-filter:none;filter:none}}@-moz-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-webkit-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-o-keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@keyframes to_hide{0%{opacity:1;-ms-filter:none;filter:none}100%{opacity:0}}@-moz-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-webkit-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-o-keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@keyframes ribbon_to_show{0%{opacity:0}100%{opacity:.6}}@-moz-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes avatar_turn_around{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes sub_menus{0%{opacity:0;-webkit-transform:translateY(10px);-moz-transform:translateY(10px);-o-transform:translateY(10px);-ms-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes donate_effcet{0%{opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-o-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px)}100%{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@-o-keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}@keyframes sidebarItem{0%{-webkit-transform:translateX(200px);-moz-transform:translateX(200px);-o-transform:translateX(200px);-ms-transform:translateX(200px);transform:translateX(200px)}100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}}:root{--docsearch-primary-color:#8fbc8f!important;--docsearch-logo-color:#8fbc8f!important;--global-font-size:14px;--global-bg:#fff;--font-color:#4c4948;--hr-border:#c7dec7;--hr-before-color:#b1d0b1;--search-bg:#f6f8fa;--search-input-color:#4c4948;--search-a-color:#4c4948;--preloader-bg:#37474f;--preloader-color:#fff;--tab-border-color:#f0f0f0;--tab-botton-bg:#f0f0f0;--tab-botton-color:#1f2d3d;--tab-button-hover-bg:#dcdcdc;--tab-button-active-bg:#fff;--card-bg:#fff;--sidebar-bg:#f6f8fa;--btn-hover-color:#ff7242;--btn-color:#fff;--btn-bg:#8fbc8f;--text-bg-hover:rgba(143,188,143,0.7);--light-grey:#eee;--dark-grey:#cacaca;--white:#fff;--text-highlight-color:#1f2d3d;--blockquote-color:#6a737d;--blockquote-bg:rgba(73,177,245,0.1);--reward-pop:#f5f5f5;--toc-link-color:#666261;--card-box-shadow:0 3px 8px 6px rgba(7,17,27,0.05);--card-hover-box-shadow:0 3px 8px 6px rgba(7,17,27,0.09);--pseudo-hover:#ff7242;--headline-presudo:#a0a0a0;--scrollbar-color:#8fbc8f;--default-bg-color:#8fbc8f;--zoom-bg:#fff;--mark-bg:rgba(0,0,0,0.3);--hl-color:#90a4ae;--hl-bg:#f6f8fa;--hltools-bg:#e6ebf1;--hltools-color:#90a4ae;--hlnumber-bg:#f6f8fa;--hlnumber-color:rgba(144,164,174,0.5);--hlscrollbar-bg:#dce4eb;--hlexpand-bg:linear-gradient(180deg, rgba(246,248,250,0.6), rgba(246,248,250,0.9))}body{margin:0;position:relative;min-height:100%;background:var(--global-bg);color:var(--font-color);font-size:var(--global-font-size);font-family:-apple-system,Quicksand,Nimbus Roman No9 L,PingFang SC,Hiragino Sans GB,Noto Serif SC,Microsoft Yahei,WenQuanYi Micro Hei,ST Heiti,sans-serif;line-height:2;-webkit-tap-highlight-color:transparent}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-thumb{background:var(--scrollbar-color)}::-webkit-scrollbar-track{background-color:transparent}*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color) transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input::placeholder{color:var(--font-color)}#web_bg{position:fixed;z-index:-999;width:100%;height:100%;background:-webkit-linear-gradient(45deg,#fff1eb,#ace0f9);background:-moz-linear-gradient(45deg,#fff1eb,#ace0f9);background:-o-linear-gradient(45deg,#fff1eb,#ace0f9);background:-ms-linear-gradient(45deg,#fff1eb,#ace0f9);background:linear-gradient(45deg,#fff1eb,#ace0f9);background-attachment:local;background-position:center;background-size:cover;background-repeat:no-repeat}h1,h2,h3,h4,h5,h6{position:relative;margin:20px 0 14px;color:var(--text-highlight-color);font-weight:700}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-size:inherit!important}.table-wrap{overflow-x:scroll;margin:0 0 20px}table{display:table;width:100%;border-spacing:0;border-collapse:collapse;empty-cells:show}table thead{background:rgba(153,169,191,.1)}table td,table th{padding:6px 12px;border:1px solid var(--light-grey);vertical-align:middle}::selection{background:#00c4b6;color:#f7f7f7}button{padding:0;outline:0;border:none;background:0 0;cursor:pointer;touch-action:manipulation}a{background-color:transparent;color:#99a9bf;text-decoration:none;word-wrap:break-word;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;-ms-transition:.2s;transition:.2s;overflow-wrap:break-word}a:hover{color:#8fbc8f}.is-center{text-align:center}.pull-left{float:left}.pull-right{float:right}img:not([src]),img[src='']{opacity:0}img[data-lazy-src]:not(.loaded){filter:blur(8px) brightness(1)}img[data-lazy-src].error{filter:none}.img-alt{margin:-10px 0 10px;color:#858585}.img-alt:hover{text-decoration:none!important}blockquote{margin:0 0 20px;padding:12px 15px;border-left:3px solid #49b1f5;background-color:var(--blockquote-bg);color:var(--blockquote-color)}blockquote footer cite:before{padding:0 5px;content:'—'}blockquote>:last-child{margin-bottom:0!important}figure.highlight table{scrollbar-color:var(--hlscrollbar-bg) transparent}figure.highlight table::-webkit-scrollbar-thumb{background:var(--hlscrollbar-bg)}figure.highlight pre .deletion{color:#bf42bf}figure.highlight pre .addition{color:#105ede}figure.highlight pre .meta{color:#7c4dff}figure.highlight pre .comment{color:rgba(149,165,166,.8)}figure.highlight pre .attribute,figure.highlight pre .css .class,figure.highlight pre .css .id,figure.highlight pre .css .pseudo,figure.highlight pre .html .doctype,figure.highlight pre .regexp,figure.highlight pre .ruby .constant,figure.highlight pre .tag .name,figure.highlight pre .variable,figure.highlight pre .xml .doctype,figure.highlight pre .xml .pi,figure.highlight pre .xml .tag .title{color:#e53935}figure.highlight pre .tag{color:#39adb5}figure.highlight pre .command,figure.highlight pre .constant,figure.highlight pre .literal,figure.highlight pre .number,figure.highlight pre .params,figure.highlight pre .preprocessor{color:#f76d47}figure.highlight pre .built_in{color:#ffb62c}figure.highlight pre .css .rules .attribute,figure.highlight pre .formula,figure.highlight pre .header,figure.highlight pre .inheritance,figure.highlight pre .number,figure.highlight pre .ruby .class .title,figure.highlight pre .ruby .symbol,figure.highlight pre .special,figure.highlight pre .string,figure.highlight pre .value,figure.highlight pre .xml .cdata{color:#91b859}figure.highlight pre .css .hexcolor,figure.highlight pre .keyword,figure.highlight pre .title{color:#39adb5}figure.highlight pre .coffeescript .title,figure.highlight pre .function,figure.highlight pre .javascript .title,figure.highlight pre .perl .sub,figure.highlight pre .python .decorator,figure.highlight pre .python .title,figure.highlight pre .ruby .function .title,figure.highlight pre .ruby .title .keyword{color:#6182b8}figure.highlight pre .javascript .function,figure.highlight pre .tag .attr{color:#7c4dff}#article-container figure.highlight .line:before{display:inline-block;padding:0 6px 0 0;min-width:30px;color:var(--hlnumber-color);content:counter(line);counter-increment:line;text-align:left}#article-container figure.highlight .line.marked{background-color:rgba(128,203,196,.251)}#article-container figure.highlight table{display:block;overflow:auto;border:none}#article-container figure.highlight table td{padding:0;border:none}#article-container figure.highlight .gutter pre{padding-right:10px;padding-left:10px;background-color:var(--hlnumber-bg);color:var(--hlnumber-color);text-align:right}#article-container figure.highlight .code pre{padding-right:10px;padding-left:10px;width:100%}#article-container figure.highlight,#article-container pre{overflow:auto;margin:0 0 20px;padding:0;background:var(--hl-bg);color:var(--hl-color);line-height:1.6;counter-reset:line;white-space:pre-wrap}#article-container code,#article-container pre{font-size:var(--global-font-size);font-family:consolas,Menlo,Noto Sans Mono,monospace!important}#article-container code{padding:2px 4px;background:rgba(27,31,35,.05);color:#f47466}#article-container pre{padding:10px 20px}#article-container pre code{padding:0;background:0 0;color:var(--hl-color);text-shadow:none}#article-container figure.highlight pre{margin:0;padding:8px 0;border:none}#article-container figure.highlight .caption,#article-container figure.highlight figcaption{padding:6px 0 2px 14px;font-size:var(--global-font-size);line-height:1em}#article-container figure.highlight .caption a,#article-container figure.highlight figcaption a{float:right;padding-right:10px;color:var(--hl-color)}#article-container figure.highlight .caption a:hover,#article-container figure.highlight figcaption a:hover{border-bottom-color:var(--hl-color)}#article-container figure.highlight.copy-true{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}#article-container figure.highlight.copy-true>pre,#article-container figure.highlight.copy-true>table{display:block!important;opacity:0}#article-container .highlight-tools{position:relative;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;overflow:hidden;min-height:24px;height:2.15em;background:var(--hltools-bg);color:var(--hltools-color);font-size:var(--global-font-size)}#article-container .highlight-tools.closed~*{display:none}#article-container .highlight-tools .expand{position:absolute;padding:.57em .7em;cursor:pointer;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#article-container .highlight-tools .expand+.code-lang{left:1.7em}#article-container .highlight-tools .expand.closed{-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;-webkit-transform:rotate(-90deg)!important;-moz-transform:rotate(-90deg)!important;-o-transform:rotate(-90deg)!important;-ms-transform:rotate(-90deg)!important;transform:rotate(-90deg)!important}#article-container .highlight-tools .code-lang{position:absolute;left:14px;text-transform:uppercase;font-weight:700;font-size:1.15em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#article-container .highlight-tools .copy-notice{position:absolute;right:2.4em;opacity:0;-webkit-transition:opacity .4s;-moz-transition:opacity .4s;-o-transition:opacity .4s;-ms-transition:opacity .4s;transition:opacity .4s}#article-container .highlight-tools .copy-button{position:absolute;right:14px;cursor:pointer;-webkit-transition:color .2s;-moz-transition:color .2s;-o-transition:color .2s;-ms-transition:color .2s;transition:color .2s}#article-container .highlight-tools .copy-button:hover{color:#8fbc8f}#article-container .gutter{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#article-container .gist table{width:auto}#article-container .gist table td{border:none}#article-container figure.highlight{position:relative;margin:0 0 24px;border-radius:7px;-webkit-box-shadow:0 5px 10px 0 rgba(144,164,174,.4);box-shadow:0 5px 10px 0 rgba(144,164,174,.4);-webkit-transform:translateZ(0)}#article-container figure.highlight .highlight-tools:after{position:absolute;left:14px;width:12px;height:12px;border-radius:50%;background:#fc625d;-webkit-box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;content:' '}#article-container figure.highlight .highlight-tools .expand{right:0}#article-container figure.highlight .highlight-tools .expand.closed{-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;-webkit-transform:rotate(90deg)!important;-moz-transform:rotate(90deg)!important;-o-transform:rotate(90deg)!important;-ms-transform:rotate(90deg)!important;transform:rotate(90deg)!important}#article-container figure.highlight .highlight-tools .expand~.copy-notice{right:3.45em}#article-container figure.highlight .highlight-tools .expand~.copy-button{right:2.1em}#article-container figure.highlight .highlight-tools .code-lang{left:75px}#article-container .code-expand-btn{position:absolute;bottom:0;z-index:10;width:100%;background:var(--hlexpand-bg);text-align:center;font-size:var(--global-font-size);cursor:pointer}#article-container .code-expand-btn i{padding:6px 0;color:var(--hlnumber-color);-webkit-animation:1.2s infinite code-expand-key;-moz-animation:1.2s infinite code-expand-key;-o-animation:1.2s infinite code-expand-key;-ms-animation:code-expand-key 1.2s infinite;animation:1.2s infinite code-expand-key}#article-container .code-expand-btn.expand-done>i{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}#article-container .code-expand-btn.expand-done+pre,#article-container .code-expand-btn.expand-done+table{margin-bottom:1.8em}#article-container .code-expand-btn:not(.expand-done)~pre,#article-container .code-expand-btn:not(.expand-done)~table{overflow:hidden;height:450px}@-moz-keyframes code-expand-key{0%,100%{opacity:.6}50%{opacity:.1}}@-webkit-keyframes code-expand-key{0%,100%{opacity:.6}50%{opacity:.1}}@-o-keyframes code-expand-key{0%,100%{opacity:.6}50%{opacity:.1}}@keyframes code-expand-key{0%,100%{opacity:.6}50%{opacity:.1}}.error404 #error-wrap{position:absolute;top:50%;right:0;left:0;margin:0 auto;padding:60px 20px 0;max-width:1000px;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}.error404 #error-wrap .error-content{overflow:hidden;margin:0 20px;height:360px}.error404 #error-wrap .error-content .error-img{display:inline-block;overflow:hidden;width:50%;height:100%}@media screen and (max-width:768px){.error404 #error-wrap .error-content{margin:0;height:500px}.error404 #error-wrap .error-content .error-img{width:100%;height:45%}}.error404 #error-wrap .error-content .error-img img{background-color:#8fbc8f}.error404 #error-wrap .error-content .error-info{display:-webkit-inline-box;display:-moz-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-box;display:inline-flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-moz-box-pack:center;-o-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;width:50%;height:100%;vertical-align:top;text-align:center}.error404 #error-wrap .error-content .error-info .error_title{margin-top:-.6em;font-size:9em}@media screen and (max-width:768px){.error404 #error-wrap .error-content .error-info{width:100%;height:55%}.error404 #error-wrap .error-content .error-info .error_title{font-size:8em}}.error404 #error-wrap .error-content .error-info .error_subtitle{margin-top:-3em;word-break:break-word;font-size:1.6em;-webkit-line-clamp:2}.error404+#rightside{display:none}.article-sort{margin-left:10px;padding-left:20px;border-left:2px solid #cfe2cf}.article-sort-title{position:relative;margin-left:10px;padding-bottom:20px;padding-left:20px;font-size:1.72em}.article-sort-title:hover:before{border-color:var(--pseudo-hover)}.article-sort-title:before{position:absolute;top:calc(((100% - 36px)/ 2));left:-9px;z-index:1;width:10px;height:10px;border:5px solid #8fbc8f;border-radius:10px;background:var(--card-bg);content:'';line-height:10px;-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out}.article-sort-title:after{position:absolute;bottom:0;left:0;z-index:0;width:2px;height:1.5em;background:#cfe2cf;content:''}.article-sort-item{position:relative;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;margin:0 0 20px 10px;-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out}.article-sort-item:hover:before{border-color:var(--pseudo-hover)}.article-sort-item:before{position:absolute;left:calc(-20px - 17px);width:6px;height:6px;border:3px solid #8fbc8f;border-radius:6px;background:var(--card-bg);content:'';-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out}.article-sort-item.no-article-cover{height:80px}.article-sort-item.no-article-cover .article-sort-item-info{padding:0}.article-sort-item.year{font-size:1.43em}.article-sort-item.year:hover:before{border-color:#8fbc8f}.article-sort-item.year:before{border-color:var(--pseudo-hover)}.article-sort-item-time{color:#858585;font-size:95%}.article-sort-item-time time{padding-left:6px;cursor:default}.article-sort-item-title{color:var(--font-color);font-size:1.1em;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;-webkit-line-clamp:2}.article-sort-item-title:hover{color:#8fbc8f;-webkit-transform:translateX(10px);-moz-transform:translateX(10px);-o-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}.article-sort-item-img{overflow:hidden;width:80px;height:80px}.article-sort-item-info{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:0 16px}.category-lists .category-title{font-size:2.57em}.category-lists .category-list{margin-bottom:0}.category-lists .category-list a{color:var(--font-color)}.category-lists .category-list a:hover{color:#8fbc8f}.category-lists .category-list .category-list-count{margin-left:8px;color:#858585}.category-lists .category-list .category-list-count:before{content:'('}.category-lists .category-list .category-list-count:after{content:')'}.category-lists ul{padding:0 0 0 20px}.category-lists ul ul{padding-left:4px}.category-lists ul li{position:relative;margin:6px 0;padding:.12em .4em .12em 1.4em}#body-wrap{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-height:100vh}.layout{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1 auto;-ms-flex:1 auto;flex:1 auto;margin:0 auto;padding:40px 15px;max-width:1200px;width:100%}@media screen and (max-width:900px){.layout{-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}.layout>div:first-child:not(.recent-posts){-webkit-align-self:flex-start;align-self:flex-start;-ms-flex-item-align:start;padding:50px 40px}.layout>div:first-child{width:74%;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}.layout.hide-aside{max-width:1000px}@media screen and (min-width:2000px){.layout{max-width:70%}.layout.hide-aside{max-width:1300px}}.layout.hide-aside>div{width:100%!important}.apple #page-header.full_page{background-attachment:scroll!important}.apple .avatar-img,.apple .flink-item-icon,.apple .recent-post-item{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-o-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}#article-container .flink{margin-bottom:20px}#article-container .flink .flink-list{overflow:auto;padding:10px 10px 0;text-align:center}#article-container .flink .flink-list>.flink-list-item{position:relative;float:left;overflow:hidden;margin:15px 7px;width:calc(100% / 3 - 15px);height:90px;border-radius:8px;line-height:17px;-webkit-transform:translateZ(0)}@media screen and (max-width:1024px){#article-container .flink .flink-list>.flink-list-item{width:calc(50% - 15px)!important}}@media screen and (max-width:600px){#article-container .flink .flink-list>.flink-list-item{width:calc(100% - 15px)!important}}#article-container .flink .flink-list>.flink-list-item:hover .flink-item-icon{margin-left:-10px;width:0}#article-container .flink .flink-list>.flink-list-item:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;background:var(--text-bg-hover);content:'';-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;-ms-transition:-ms-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:scale(0);-moz-transform:scale(0);-o-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}#article-container .flink .flink-list>.flink-list-item:active:before,#article-container .flink .flink-list>.flink-list-item:focus:before,#article-container .flink .flink-list>.flink-list-item:hover:before{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}#article-container .flink .flink-list>.flink-list-item a{color:var(--font-color);text-decoration:none}#article-container .flink .flink-list>.flink-list-item a .flink-item-icon{float:left;overflow:hidden;margin:15px 10px;width:60px;height:60px;border-radius:35px;-webkit-transition:width .3s ease-out;-moz-transition:width .3s ease-out;-o-transition:width .3s ease-out;-ms-transition:width .3s ease-out;transition:width .3s ease-out}#article-container .flink .flink-list>.flink-list-item a .flink-item-icon img{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .3s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .3s;-o-transition:filter 375ms ease-in .2s,-o-transform .3s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .3s;transition:filter 375ms ease-in .2s,transform .3s;object-fit:cover}#article-container .flink .flink-list>.flink-list-item a .img-alt{display:none}#article-container .flink .flink-item-name{padding:16px 10px 0 0;height:40px;font-weight:700;font-size:1.43em}#article-container .flink .flink-item-desc{padding:16px 10px 16px 0;height:50px;font-size:.93em}#article-container .flink .flink-name{margin-bottom:5px;font-weight:700;font-size:1.5em}#recent-posts>.recent-post-item:not(:first-child){margin-top:20px}#recent-posts>.recent-post-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;overflow:hidden;height:16.8em}#recent-posts>.recent-post-item:hover img.post-bg{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}#recent-posts>.recent-post-item.ads-wrap{display:block!important;height:auto!important}#recent-posts>.recent-post-item .post_cover{overflow:hidden;width:42%;height:100%}@media screen and (max-width:768px){.category-lists .category-title{font-size:2em}.layout{padding:20px 5px}.layout>div:first-child:not(.recent-posts){padding:36px 14px}#recent-posts>.recent-post-item{-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:auto}#recent-posts>.recent-post-item .post_cover{width:100%;height:230px}}#recent-posts>.recent-post-item .post_cover.right{-webkit-box-ordinal-group:1;-moz-box-ordinal-group:1;-o-box-ordinal-group:1;-ms-flex-order:1;-webkit-order:1;order:1}#recent-posts>.recent-post-item>.recent-post-info{padding:0 40px;width:58%}#recent-posts>.recent-post-item>.recent-post-info.no-cover{width:100%}#recent-posts>.recent-post-item>.recent-post-info>.article-title{color:var(--text-highlight-color);font-size:1.55em;line-height:1.4;-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out;-webkit-line-clamp:2}#recent-posts>.recent-post-item>.recent-post-info>.article-title .sticky{margin-right:10px;color:#ff7242;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}@media screen and (max-width:768px){#recent-posts>.recent-post-item .post_cover.right{-webkit-box-ordinal-group:0;-moz-box-ordinal-group:0;-o-box-ordinal-group:0;-ms-flex-order:0;-webkit-order:0;order:0}#recent-posts>.recent-post-item>.recent-post-info{padding:20px 20px 30px;width:100%}#recent-posts>.recent-post-item>.recent-post-info.no-cover{padding:30px 20px}#recent-posts>.recent-post-item>.recent-post-info>.article-title{font-size:1.43em}.tag-cloud-list a{zoom:0.85}}#recent-posts>.recent-post-item>.recent-post-info>.article-title:hover{color:#8fbc8f}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap{margin:6px 0;color:#858585;font-size:.9em}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap>.post-meta-date{cursor:default}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap i{margin:0 4px 0 0}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .fa-spinner{margin:0}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-label{padding-right:4px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-separator{margin:0 6px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap .article-meta-link{margin:0 4px}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap a{color:#858585}#recent-posts>.recent-post-item>.recent-post-info>.article-meta-wrap a:hover{color:#8fbc8f;text-decoration:underline}#recent-posts>.recent-post-item>.recent-post-info>.content{-webkit-line-clamp:2}.tag-cloud-list a{display:inline-block;padding:0 8px;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}.tag-cloud-list a:hover{color:#8fbc8f!important;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.tag-cloud-title{font-size:2.57em}h1.page-title+.tag-cloud-list{text-align:left}#aside-content{width:26%}#aside-content>.card-widget:first-child{margin-top:0}@media screen and (max-width:900px){.layout>div:first-child{width:100%!important}#aside-content{width:100%}#aside-content>.card-widget:first-child{margin-top:20px}}#aside-content .card-widget{position:relative;overflow:hidden;margin-top:20px;padding:20px 24px}#aside-content .card-info .author-info__name{font-weight:500;font-size:1.57em}#aside-content .card-info .author-info__description{margin-top:-.42em}#aside-content .card-info .card-info-data{margin:14px 0 4px}#aside-content .card-info .card-info-social-icons{margin:6px 0 -6px}#aside-content .card-info .card-info-social-icons .social-icon{margin:0 10px;color:var(--font-color);font-size:1.4em}#aside-content .card-info .card-info-social-icons i{-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}#aside-content .card-info .card-info-social-icons i:hover{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}#aside-content .card-info #card-info-btn{display:block;margin-top:14px;background-color:var(--btn-bg);color:var(--btn-color);text-align:center;line-height:2.4}#aside-content .card-info #card-info-btn:hover{background-color:var(--btn-hover-color)}#aside-content .card-info #card-info-btn span{padding-left:10px}#aside-content .item-headline{padding-bottom:6px;font-size:1.2em}#aside-content .item-headline span{margin-left:6px}@media screen and (min-width:900px){#aside-content{padding-left:15px}#aside-content .sticky_layout{position:sticky;position:-webkit-sticky;top:20px;-webkit-transition:top .3s;-moz-transition:top .3s;-o-transition:top .3s;-ms-transition:top .3s;transition:top .3s}}#aside-content .card-tag-cloud a{display:inline-block;padding:0 4px}#aside-content .card-tag-cloud a:hover{color:#8fbc8f!important}#aside-content .aside-list>span{display:block;margin-bottom:10px;text-align:center}#aside-content .aside-list>.aside-list-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:6px 0}#aside-content .aside-list>.aside-list-item:first-child{padding-top:0}#aside-content .aside-list>.aside-list-item:not(:last-child){border-bottom:1px dashed #f5f5f5}#aside-content .aside-list>.aside-list-item:last-child{padding-bottom:0}#aside-content .aside-list>.aside-list-item .thumbnail{overflow:hidden;width:4.2em;height:4.2em}#aside-content .aside-list>.aside-list-item .content{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding-left:10px;word-break:break-all}#aside-content .aside-list>.aside-list-item .content>.name{-webkit-line-clamp:1}#aside-content .aside-list>.aside-list-item .content>.name,#aside-content .aside-list>.aside-list-item .content>time{display:block;color:#858585;font-size:85%}#aside-content .aside-list>.aside-list-item .content>.comment,#aside-content .aside-list>.aside-list-item .content>.title{color:var(--font-color);font-size:95%;line-height:1.5;-webkit-line-clamp:2}#aside-content .aside-list>.aside-list-item .content>.comment:hover,#aside-content .aside-list>.aside-list-item .content>.title:hover{color:#8fbc8f}#aside-content .aside-list>.aside-list-item.no-cover{min-height:4.4em}#aside-content .card-archives ul.card-archive-list,#aside-content .card-categories ul.card-category-list{margin:0;padding:0;list-style:none}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a,#aside-content .card-categories ul.card-category-list>.card-category-list-item a{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:3px 10px;color:var(--font-color);-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a:hover,#aside-content .card-categories ul.card-category-list>.card-category-list-item a:hover{padding:3px 17px;background-color:var(--text-bg-hover)}#aside-content .card-archives ul.card-archive-list>.card-archive-list-item a span:first-child,#aside-content .card-categories ul.card-category-list>.card-category-list-item a span:first-child{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}#aside-content .card-categories .card-category-list.child{padding:0 0 0 16px}#aside-content .card-categories .card-category-list>.parent>a .card-category-list-name{width:70%!important}#aside-content .card-categories .card-category-list>.parent>a .card-category-list-count{width:calc(100% - 70% - 20px);text-align:right}#aside-content .card-categories .card-category-list>.parent i{float:right;margin-right:-.5em;padding:.5em;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s;-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}#aside-content .card-categories .card-category-list>.parent i.expand{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}#aside-content .card-webinfo .webinfo .webinfo-item{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:2px 10px 0}#aside-content .card-webinfo .webinfo .webinfo-item div:first-child{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding-right:20px}@media screen and (min-width:901px){#aside-content #card-toc{right:0!important}}#aside-content #card-toc .toc-percentage{float:right;margin-top:-9px;color:#a9a9a9;font-style:italic;font-size:140%}#aside-content #card-toc .toc-content{overflow-y:scroll;overflow-y:overlay;margin:0 -24px;max-height:calc(100vh - 120px)}#aside-content #card-toc .toc-content>*{margin:0 20px!important}#aside-content #card-toc .toc-content>*>.toc-item>.toc-child{margin-left:10px;padding-left:10px;border-left:1px solid var(--dark-grey)}#aside-content #card-toc .toc-content:not(.is-expand) .toc-child{display:none}@media screen and (max-width:900px){#aside-content #card-toc{position:fixed;right:-100%;bottom:30px;z-index:100;max-width:380px;max-height:calc(100% - 60px);width:calc(100% - 80px);opacity:0;-webkit-transition:initial;-moz-transition:initial;-o-transition:initial;-ms-transition:initial;transition:initial;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-o-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom}#aside-content #card-toc .toc-content{max-height:calc(100vh - 140px)}#aside-content #card-toc .toc-content:not(.is-expand) .toc-child{display:block!important}}#aside-content #card-toc .toc-content:not(.is-expand) .toc-item.active .toc-child{display:block}#aside-content #card-toc .toc-content li,#aside-content #card-toc .toc-content ol{list-style:none}#aside-content #card-toc .toc-content>ol{padding:0!important}#aside-content #card-toc .toc-content ol{margin:0;padding-left:18px}#aside-content #card-toc .toc-content .toc-link{display:block;margin:4px 0;padding:1px 6px;color:var(--toc-link-color);-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out}#aside-content #card-toc .toc-content .toc-link:hover{color:#8fbc8f}#aside-content #card-toc .toc-content .toc-link.active{background:#00c4b6;color:#fff}#aside-content .sticky_layout:only-child>:first-child{margin-top:0}#aside-content .card-more-btn{float:right;color:inherit}#aside-content .card-more-btn:hover{-webkit-animation:1s infinite more-btn-move;-moz-animation:1s infinite more-btn-move;-o-animation:1s infinite more-btn-move;-ms-animation:more-btn-move 1s infinite;animation:1s infinite more-btn-move}#aside-content .card-announcement .item-headline i{color:red}.avatar-img{overflow:hidden;margin:0 auto;width:110px;height:110px;border-radius:70px}.avatar-img img{width:100%;height:100%;-webkit-transition:filter 375ms ease-in .2s,-webkit-transform .3s;-moz-transition:filter 375ms ease-in .2s,-moz-transform .3s;-o-transition:filter 375ms ease-in .2s,-o-transform .3s;-ms-transition:filter 375ms ease-in .2s,-ms-transform .3s;transition:filter 375ms ease-in .2s,transform .3s;object-fit:cover}.avatar-img img:hover{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}.site-data{display:table;width:100%;table-layout:fixed}.site-data>a{display:table-cell}.site-data>a div{-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}.site-data>a:hover div{color:#8fbc8f!important}.site-data>a .headline{color:var(--font-color)}.site-data>a .length-num{margin-top:-.32em;color:var(--text-highlight-color);font-size:1.4em}@media screen and (min-width:900px){html.hide-aside .layout{-webkit-box-pack:center;-moz-box-pack:center;-o-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}html.hide-aside .layout>.aside-content{display:none}html.hide-aside .layout>div:first-child{width:80%}}.page .sticky_layout{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-o-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.page .card-recent-post{-webkit-box-ordinal-group:2;-moz-box-ordinal-group:2;-o-box-ordinal-group:2;-ms-flex-order:2;-webkit-order:2;order:2}.page #card-newest-comments{-webkit-box-ordinal-group:6;-moz-box-ordinal-group:6;-o-box-ordinal-group:6;-ms-flex-order:6;-webkit-order:6;order:6}.page .card-categories{-webkit-box-ordinal-group:4;-moz-box-ordinal-group:4;-o-box-ordinal-group:4;-ms-flex-order:4;-webkit-order:4;order:4}.page .card-tags{-webkit-box-ordinal-group:3;-moz-box-ordinal-group:3;-o-box-ordinal-group:3;-ms-flex-order:3;-webkit-order:3;order:3}.page .card-archives{-webkit-box-ordinal-group:5;-moz-box-ordinal-group:5;-o-box-ordinal-group:5;-ms-flex-order:5;-webkit-order:5;order:5}.page .card-webinfo{-webkit-box-ordinal-group:1;-moz-box-ordinal-group:1;-o-box-ordinal-group:1;-ms-flex-order:1;-webkit-order:1;order:1}@-moz-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-webkit-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-o-keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@keyframes more-btn-move{0%,100%{-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(3px);-moz-transform:translateX(3px);-o-transform:translateX(3px);-ms-transform:translateX(3px);transform:translateX(3px)}}@-moz-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-webkit-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-o-keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@keyframes toc-open{0%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}100%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-moz-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-webkit-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@-o-keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}@keyframes toc-close{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(.7);-moz-transform:scale(.7);-o-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}}#post-comment .comment-head{margin-bottom:20px}#post-comment .comment-head .comment-headline{display:inline-block;vertical-align:middle;font-weight:700;font-size:1.43em}#post-comment .comment-head #comment-switch{display:inline-block;float:right;margin:2px auto 0;padding:4px 16px;width:max-content;border-radius:8px;background:#f6f8fa}#post-comment .comment-head #comment-switch .first-comment{color:#49b1f5}#post-comment .comment-head #comment-switch .second-comment{color:#ff7242}#post-comment .comment-head #comment-switch .switch-btn{position:relative;display:inline-block;margin:-4px 8px 0;width:42px;height:22px;border-radius:34px;background-color:#49b1f5;vertical-align:middle;cursor:pointer;-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#post-comment .comment-head #comment-switch .switch-btn:before{position:absolute;bottom:4px;left:4px;width:14px;height:14px;border-radius:50%;background-color:#fff;content:'';-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#post-comment .comment-head #comment-switch .switch-btn.move{background-color:#ff7242}#post-comment .comment-head #comment-switch .switch-btn.move:before{-webkit-transform:translateX(20px);-moz-transform:translateX(20px);-o-transform:translateX(20px);-ms-transform:translateX(20px);transform:translateX(20px)}#post-comment .comment-wrap>div:nth-child(2){display:none}#footer{position:relative;background-color:#8fbc8f;background-attachment:scroll;background-position:bottom;background-size:cover}#footer:before{position:absolute;width:100%;height:100%;background-color:var(--mark-bg);content:''}#footer-wrap{position:relative;padding:40px 20px;color:var(--light-grey);text-align:center}#footer-wrap a{color:var(--light-grey)}#footer-wrap a:hover{text-decoration:underline}#footer-wrap .footer-separator{margin:0 4px}#footer-wrap .gongan-icon,#footer-wrap .icp-icon{padding:0 4px;max-height:1.4em;width:auto;vertical-align:text-bottom}#page-header{position:relative;width:100%;background-color:#8fbc8f;background-position:center center;background-size:cover;background-repeat:no-repeat;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s}#page-header:not(.not-top-img):before{position:absolute;width:100%;height:100%;background-color:var(--mark-bg);content:''}#page-header.full_page{height:100vh;background-attachment:fixed}#page-header.full_page #site-info{position:absolute;top:43%;padding:0 10px;width:100%}#page-header #scroll-down .scroll-down-effects,#page-header #site-subtitle,#page-header #site-title{text-align:center;text-shadow:2px 2px 4px rgba(0,0,0,.15);line-height:1.5}#page-header #site-title{margin:0;color:var(--white);font-size:1.85em}@media screen and (min-width:768px){#page-header #site-title{font-size:2.85em}}#page-header #site-subtitle{color:var(--light-grey);font-size:1.15em}@media screen and (min-width:768px){#page-header #site-subtitle{font-size:1.72em}#post-info #post-meta>.meta-secondline>span:first-child{display:none}}#page-header #site_social_icons{display:none;margin:0 auto;width:300px;text-align:center}#page-header #site_social_icons .social-icon{margin:0 10px;color:var(--light-grey);text-shadow:2px 2px 4px rgba(0,0,0,.15);font-size:1.43em}#page-header #scroll-down{position:absolute;bottom:0;width:100%;cursor:pointer}#page-header #scroll-down .scroll-down-effects{position:relative;width:100%;color:var(--light-grey);font-size:30px}#page-header.not-home-page{height:400px}#page-header #page-site-info{position:absolute;top:200px;padding:0 10px;width:100%}@media screen and (max-width:768px){.tag-cloud-title{font-size:2em}#page-header #site_social_icons{display:block}#page-header.not-home-page{height:280px}#page-header #page-site-info{top:140px}}#page-header.post-bg{height:400px}#page-header #post-info{position:absolute;bottom:100px;padding:0 8%;width:100%;text-align:center}@media screen and (max-width:900px){#page-header #post-info{bottom:30px;text-align:left}}@media screen and (max-width:768px){#page-header.post-bg{height:360px}#page-header #post-info{bottom:22px;padding:0 22px}}#page-header.not-top-img{margin-bottom:10px;height:60px;background:0}#page-header.not-top-img #nav{background:rgba(255,255,255,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,.6);box-shadow:0 5px 6px -5px rgba(133,133,133,.6)}#page-header.not-top-img #nav .site-name,#page-header.not-top-img #nav a{color:var(--font-color);text-shadow:none}#page-header.nav-fixed #nav{position:fixed;top:-60px;z-index:91;background:rgba(255,255,255,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,.6);box-shadow:0 5px 6px -5px rgba(133,133,133,.6);-webkit-transition:-webkit-transform .2s ease-in-out,opacity .2s ease-in-out;-moz-transition:-moz-transform .2s ease-in-out,opacity .2s ease-in-out;-o-transition:-o-transform .2s ease-in-out,opacity .2s ease-in-out;-ms-transition:-ms-transform .2s ease-in-out,opacity .2s ease-in-out;transition:transform .2s ease-in-out,opacity .2s ease-in-out}#page-header.nav-fixed #nav #blog-info{color:var(--font-color)}#page-header.nav-fixed #nav #blog-info:hover{color:#8fbc8f}#page-header.nav-fixed #nav #blog-info .site-name{text-shadow:none}#page-header.nav-fixed #nav #toggle-menu,#page-header.nav-fixed #nav a{color:var(--font-color);text-shadow:none}#page-header.nav-fixed #nav #toggle-menu:hover,#page-header.nav-fixed #nav a:hover{color:#8fbc8f}#page-header.nav-fixed.fixed #nav{top:0;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s}#page-header.nav-visible:not(.fixed) #nav{-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s;-webkit-transform:translate3d(0,100%,0);-moz-transform:translate3d(0,100%,0);-o-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}#page-header.nav-visible:not(.fixed)+.layout>.aside-content>.sticky_layout{top:70px;-webkit-transition:top .5s;-moz-transition:top .5s;-o-transition:top .5s;-ms-transition:top .5s;transition:top .5s}#page-header.fixed #nav{position:fixed}#page-header.fixed+.layout>.aside-content>.sticky_layout{top:70px;-webkit-transition:top .5s;-moz-transition:top .5s;-o-transition:top .5s;-ms-transition:top .5s;transition:top .5s}#page-header.fixed+.layout #card-toc .toc-content{max-height:calc(100vh - 170px)}#page h1.page-title{margin:8px 0 20px}#post>#post-info{margin-bottom:30px}#post>#post-info .post-title{padding-bottom:4px;border-bottom:1px solid var(--light-grey);color:var(--text-highlight-color)}#post>#post-info .post-title .post-edit-link{float:right}#post>#post-info #post-meta,#post>#post-info #post-meta a{color:#78818a}#post-info .post-title{margin-bottom:8px;color:var(--white);font-weight:400;font-size:2.5em;line-height:1.5;-webkit-line-clamp:3}#post-info .post-title .post-edit-link{padding-left:10px}#post-info #post-meta{color:var(--light-grey);font-size:95%}#post-info #post-meta .post-meta-separator{margin:0 5px}#post-info #post-meta .post-meta-icon,#post-info #post-meta .post-meta-label{margin-right:4px}#post-info #post-meta a{color:var(--light-grey);-webkit-transition:.3s ease-out;-moz-transition:.3s ease-out;-o-transition:.3s ease-out;-ms-transition:.3s ease-out;transition:.3s ease-out}#post-info #post-meta a:hover{color:#8fbc8f;text-decoration:underline}#nav{position:absolute;top:0;z-index:90;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:0 36px;width:100%;height:60px;font-size:1.3em;opacity:0;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s}@media screen and (max-width:768px){#post-info .post-title{font-size:2.1em}#post-info #post-meta{font-size:90%}#post-info #post-meta>.meta-firstline,#post-info #post-meta>.meta-secondline{display:inline}#nav{padding:0 16px}}#nav.show{opacity:1;-ms-filter:none;filter:none}#nav #blog-info{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;color:var(--light-grey)}#nav #blog-info .site-icon{margin-right:6px;height:36px;vertical-align:middle}#nav #toggle-menu{display:none;padding:2px 0 0 6px;vertical-align:top}#nav #toggle-menu:hover,#nav a:hover{color:var(--white)}#nav a{color:var(--light-grey)}#nav .site-name{text-shadow:2px 2px 4px rgba(0,0,0,.15);font-weight:700}#nav .menus_items{display:inline}#nav .menus_items .menus_item{position:relative;display:inline-block;padding:0 0 0 14px}#nav .menus_items .menus_item:hover .menus_item_child{display:block}#nav .menus_items .menus_item:hover>a>i:last-child{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}#nav .menus_items .menus_item>a>i:last-child{padding:4px;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#nav .menus_items .menus_item .menus_item_child{position:absolute;right:0;display:none;margin-top:8px;padding:0;width:max-content;border-radius:5px;background-color:var(--sidebar-bg);-webkit-box-shadow:0 5px 20px -4px rgba(0,0,0,.5);box-shadow:0 5px 20px -4px rgba(0,0,0,.5);-webkit-animation:.3s .1s both sub_menus;-moz-animation:.3s .1s both sub_menus;-o-animation:.3s .1s both sub_menus;-ms-animation:sub_menus 0.3s 0.1s ease both;animation:.3s .1s both sub_menus}#nav .menus_items .menus_item .menus_item_child:before{position:absolute;top:-8px;left:0;width:100%;height:20px;content:''}#nav .menus_items .menus_item .menus_item_child li{list-style:none}#nav .menus_items .menus_item .menus_item_child li:hover{background:var(--text-bg-hover)}#nav .menus_items .menus_item .menus_item_child li:first-child{border-top-left-radius:5px;border-top-right-radius:5px}#nav .menus_items .menus_item .menus_item_child li:last-child{border-bottom-right-radius:5px;border-bottom-left-radius:5px}#nav .menus_items .menus_item .menus_item_child li a{display:inline-block;padding:8px 16px;width:100%;color:var(--font-color)!important;text-shadow:none!important}#nav.hide-menu #toggle-menu{display:inline-block!important}#nav.hide-menu #toggle-menu .site-page{font-size:inherit}#nav.hide-menu #search-button span,#nav.hide-menu .menus_items,#nav.hide-menu .toRandomPost span{display:none}#nav #search-button{display:inline;padding:0 0 0 14px}#nav .site-page{position:relative;padding-bottom:6px;text-shadow:1px 1px 2px rgba(0,0,0,.3);font-size:.78em;cursor:pointer}#nav .site-page:not(.child):after{position:absolute;bottom:0;left:0;z-index:-1;width:0;height:3px;background-color:#b1d0b1;content:'';-webkit-transition:.3s ease-in-out;-moz-transition:.3s ease-in-out;-o-transition:.3s ease-in-out;-ms-transition:.3s ease-in-out;transition:.3s ease-in-out}#nav .site-page:not(.child):hover:after{width:100%}#pagination .pagination{margin-top:20px;text-align:center}#pagination .page-number.current{background:#00c4b6;color:var(--white)}#pagination .pagination-info{position:absolute;top:50%;padding:20px 40px;width:100%;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}#pagination .next_info,#pagination .prev_info{color:var(--white);font-weight:500}#pagination .next-post .pagination-info{text-align:right}#pagination .pull-full{width:100%!important}#pagination .next-post .label,#pagination .prev-post .label{color:var(--light-grey);text-transform:uppercase;font-size:90%}#pagination .next-post,#pagination .prev-post{width:50%}#pagination .next-post a,#pagination .prev-post a{position:relative;display:block;overflow:hidden;height:150px}#pagination.pagination-post{overflow:hidden;margin-top:40px;width:100%;background:#000}.layout>.recent-posts .pagination>*{display:inline-block;margin:0 6px;width:2.5em;height:2.5em;line-height:2.5em}.layout>.recent-posts .pagination>:not(.space):hover{background:var(--btn-hover-color);color:var(--btn-color)}.layout>div:not(.recent-posts) .pagination .page-number{display:inline-block;margin:0 4px;min-width:24px;height:24px;text-align:center;line-height:24px;cursor:pointer}#article-container{word-wrap:break-word;overflow-wrap:break-word}#article-container a{color:#ff7242}#article-container a:hover{text-decoration:underline}#article-container img{display:block;margin:0 auto 20px;max-width:100%;-webkit-transition:filter 375ms ease-in .2s;-moz-transition:filter 375ms ease-in .2s;-o-transition:filter 375ms ease-in .2s;-ms-transition:filter 375ms ease-in .2s;transition:filter 375ms ease-in .2s}#article-container p{margin:0 0 16px}#article-container iframe{margin:0 0 20px}#article-container kbd{margin:0 3px;padding:3px 5px;border:1px solid #b4b4b4;border-radius:3px;background-color:#f8f8f8;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.25),0 2px 1px 0 rgba(255,255,255,.6) inset;box-shadow:0 1px 3px rgba(0,0,0,.25),0 2px 1px 0 rgba(255,255,255,.6) inset;color:#34495e;white-space:nowrap;font-weight:600;font-size:.9em;font-family:Monaco,'Ubuntu Mono',monospace;line-height:1em}#article-container a.headerlink:after{float:right;color:var(--headline-presudo);content:'\f0c1';font-size:.95em;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;opacity:0}#article-container a.headerlink:hover:after{color:var(--pseudo-hover)}#article-container h1:hover a.headerlink:after,#article-container h2:hover a.headerlink:after,#article-container h3:hover a.headerlink:after,#article-container h4:hover a.headerlink:after,#article-container h5:hover a.headerlink:after,#article-container h6:hover a.headerlink:after{opacity:1;-ms-filter:none;filter:none}#article-container ol ol,#article-container ol ul,#article-container ul ol,#article-container ul ul{padding-left:20px}#article-container ol li,#article-container ul li{margin:4px 0}#article-container>:last-child{margin-bottom:0!important}#article-container hr{margin:20px 0}#article-container h1,#article-container h2,#article-container h3,#article-container h4,#article-container h5,#article-container h6{-webkit-transition:.2s ease-out;-moz-transition:.2s ease-out;-o-transition:.2s ease-out;-ms-transition:.2s ease-out;transition:.2s ease-out}#article-container h1:before,#article-container h2:before,#article-container h3:before,#article-container h4:before,#article-container h5:before,#article-container h6:before{position:absolute;top:calc(50% - 7px);color:#2fcc66;content:'\f13d';line-height:1;-webkit-transition:.2s ease-out;-moz-transition:.2s ease-out;-o-transition:.2s ease-out;-ms-transition:.2s ease-out;transition:.2s ease-out}#article-container h1:hover:before,#article-container h2:hover:before,#article-container h3:hover:before,#article-container h4:hover:before,#article-container h5:hover:before,#article-container h6:hover:before{color:#8fbc8f}#article-container h1,#article-container h4:hover{padding-left:32px}#article-container h1:before{margin-left:-26px;font-size:20px}#article-container h1:hover{padding-left:38px}#article-container h2,#article-container h5:hover,#article-container h6:hover{padding-left:30px}#article-container h2:before{margin-left:-24px;font-size:18px}#article-container h2:hover{padding-left:36px}#article-container h3{padding-left:28px}#article-container h3:before{margin-left:-22px;font-size:16px}#article-container h3:hover{padding-left:34px}#article-container h4{padding-left:26px}#article-container h4:before{margin-left:-20px;font-size:14px}#article-container h5,#article-container h6{padding-left:24px}#article-container h5:before,#article-container h6:before{margin-left:-18px;font-size:12px}#article-container ol p,#article-container ul p{margin:0 0 8px}#article-container li::marker{color:#8fbc8f;font-weight:600;font-size:1.05em}#article-container li:hover::marker{color:var(--pseudo-hover)}#article-container ul>li{list-style-type:circle}#post .tag_share:after{display:block;clear:both;content:''}#post .tag_share .post-meta__tag-list{display:inline-block}#post .tag_share .post-meta__tags{display:inline-block;margin:8px 8px 8px 0;padding:0 12px;width:fit-content;border:1px solid #8fbc8f;border-radius:12px;color:#8fbc8f;font-size:.85em;-webkit-transition:.2s ease-in-out;-moz-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;-ms-transition:.2s ease-in-out;transition:.2s ease-in-out}#post .tag_share .post-meta__tags:hover{background:#8fbc8f;color:var(--white)}#post .tag_share .post_share{display:inline-block;float:right;margin:8px 0 0;width:fit-content}#post .tag_share .post_share .social-share{font-size:.85em}#post .tag_share .post_share .social-share .social-share-icon{margin:0 4px;width:1.85em;height:1.85em;font-size:1.2em;line-height:1.85em}#post .post-copyright{position:relative;margin:40px 0 10px;padding:10px 16px;border:1px solid var(--light-grey);-webkit-transition:box-shadow .3s ease-in-out;-moz-transition:box-shadow .3s ease-in-out;-o-transition:box-shadow .3s ease-in-out;-ms-transition:box-shadow .3s ease-in-out;transition:box-shadow .3s ease-in-out}#post .post-copyright:before{position:absolute;top:2px;right:12px;color:#8fbc8f;content:'\f1f9';font-size:1.3em}#post .post-copyright:hover{-webkit-box-shadow:0 0 8px 0 rgba(232,237,250,.6),0 2px 4px 0 rgba(232,237,250,.5);box-shadow:0 0 8px 0 rgba(232,237,250,.6),0 2px 4px 0 rgba(232,237,250,.5)}#post .post-copyright .post-copyright-meta{color:#8fbc8f;font-weight:700}#post .post-copyright .post-copyright-info{padding-left:6px}#post .post-copyright .post-copyright-info a{text-decoration:underline;word-break:break-word}#post .post-copyright .post-copyright-info a:hover{text-decoration:none}#post .post-outdate-notice{position:relative;margin:0 0 20px;padding:.5em 1em .5em 2.6em;border-radius:3px;background-color:#ffe6e6;color:#f66;border-left:5px solid #ff8080}#post .post-outdate-notice:before{position:absolute;top:50%;left:.9em;color:#ff8080;content:'\f071';-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-o-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}#post .ads-wrap{margin:40px 0}.post-ai-description{background:var(--hl-bg);border-radius:12px;padding:12px 16px;line-height:1.3;margin-bottom:10px}.ai-title{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;color:var(--font-color);border-radius:8px;-webkit-box-align:center;-moz-box-align:center;-o-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding:0 5px}.ai-title i{font-weight:800;font-size:20px;line-height:20px}.ai-title .ai-title-text{font-weight:700;margin-left:8px}#ai-tag{font-size:12px;background-color:var(--btn-bg);color:var(--btn-color);border-radius:4px;margin-left:auto;line-height:1;padding:4px 5px;cursor:pointer}#ai-Toggle{font-size:12px;background:var(--btn-bg);color:var(--btn-color);padding:4px;border-radius:4px;margin-left:6px;-webkit-transform:scale(.8);-moz-transform:scale(.8);-o-transform:scale(.8);-ms-transform:scale(.8);transform:scale(.8);cursor:pointer;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;font-weight:700}#ai-Toggle:hover{background:var(--btn-hover-color)}#go-tianli-blog{display:none}.ai-explanation{margin-top:12px;padding:8px 12px;background:var(--card-bg);border-radius:8px;font-size:15px;line-height:1.4}.ai-cursor{display:inline-block;width:7px;background:var(--font-color);height:16px;margin-bottom:-2px;opacity:.95;margin-left:3px;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}.ai-btn-box{font-size:15.5px;width:100%;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-lines:multiple;-moz-box-lines:multiple;-o-box-lines:multiple;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.ai-btn-item{padding:5px 10px;margin:10px 16px 0 5px;width:fit-content;line-height:1;background:var(--btn-bg);color:var(--btn-color);border-radius:6px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;cursor:pointer}.ai-btn-item:hover{background:var(--btn-hover-color)}.ai-recommend{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-o-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-lines:multiple;-moz-box-lines:multiple;-o-box-lines:multiple;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.ai-recommend .ai-recommend-item{width:calc(50% - 20px);margin:10px;background:var(--hltools-bg);border-radius:4px;padding:10px;cursor:pointer;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;-webkit-animation:.6s .1s backwards slide-in;-moz-animation:.6s .1s backwards slide-in;-o-animation:.6s .1s backwards slide-in;-ms-animation:slide-in 0.6s 0.1s backwards;animation:.6s .1s backwards slide-in}.ai-recommend .ai-recommend-item a{color:var(--font-color)}.ai-recommend .ai-recommend-item:hover{background:var(--btn-hover-color)}.relatedPosts{margin-top:40px}.relatedPosts>.headline{margin-bottom:5px;font-weight:700;font-size:1.43em}.relatedPosts>.relatedPosts-list>div{position:relative;display:inline-block;overflow:hidden;margin:3px;width:calc(33.333% - 6px);height:200px;background:#000;vertical-align:bottom}@media screen and (max-width:768px){#pagination .next-post,#pagination .prev-post{width:100%}.ai-btn-box{-webkit-box-pack:center;-moz-box-pack:center;-o-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.ai-recommend .ai-recommend-item{width:100%}.relatedPosts>.relatedPosts-list>div{margin:2px;width:calc(50% - 4px);height:150px}}.relatedPosts>.relatedPosts-list .content{position:absolute;top:50%;padding:0 20px;width:100%;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}.relatedPosts>.relatedPosts-list .content .date{color:var(--light-grey);font-size:90%}.relatedPosts>.relatedPosts-list .content .title{color:var(--white);-webkit-line-clamp:2}.post-reward{position:relative;margin-top:80px;width:100%;text-align:center;pointer-events:none}.post-reward>*{pointer-events:auto}.post-reward .reward-button{display:inline-block;padding:4px 24px;background:var(--btn-bg);color:var(--btn-color);cursor:pointer}.post-reward .reward-button i{margin-right:5px}.post-reward:hover .reward-button{background:var(--btn-hover-color)}.post-reward:hover>.reward-main{display:block}.post-reward .reward-main{position:absolute;bottom:40px;left:0;z-index:100;display:none;padding:0 0 15px;width:100%}.post-reward .reward-main .reward-all{display:inline-block;margin:0;padding:20px 10px;border-radius:4px;background:var(--reward-pop)}.post-reward .reward-main .reward-all:before{position:absolute;bottom:-10px;left:0;width:100%;height:20px;content:''}.post-reward .reward-main .reward-all:after{position:absolute;right:0;bottom:2px;left:0;margin:0 auto;width:0;height:0;border-top:13px solid var(--reward-pop);border-right:13px solid transparent;border-left:13px solid transparent;content:''}.post-reward .reward-main .reward-all .reward-item{display:inline-block;padding:0 8px;list-style-type:none;vertical-align:top}.post-reward .reward-main .reward-all .reward-item img{width:130px;height:130px}.post-reward .reward-main .reward-all .reward-item .post-qr-code-desc{width:130px;color:#858585}#rightside{position:fixed;right:-48px;bottom:40px;z-index:100;opacity:0;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s}#rightside #rightside-config-hide{height:0;opacity:0;-webkit-transition:-webkit-transform .4s;-moz-transition:-moz-transform .4s;-o-transition:-o-transform .4s;-ms-transition:-ms-transform .4s;transition:transform .4s;-webkit-transform:translate(45px,0);-moz-transform:translate(45px,0);-o-transform:translate(45px,0);-ms-transform:translate(45px,0);transform:translate(45px,0)}#rightside #rightside-config-hide.show{height:auto;opacity:1;-ms-filter:none;filter:none;-webkit-transform:translate(0,0);-moz-transform:translate(0,0);-o-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}#rightside #rightside-config-hide.status{height:auto;opacity:1;-ms-filter:none;filter:none}#rightside>div>a,#rightside>div>button{display:block;margin-bottom:5px;width:35px;height:35px;border-radius:5px;background-color:var(--btn-bg);color:var(--btn-color);text-align:center;font-size:16px;line-height:35px}#rightside>div>a:hover,#rightside>div>button:hover{background-color:var(--btn-hover-color)}#rightside #go-up .scroll-percent,#rightside #mobile-toc-button{display:none}@media screen and (max-width:900px){#rightside #mobile-toc-button{display:block}#rightside #hide-aside-btn{display:none}}#rightside #go-up.show-percent .scroll-percent{display:block}#rightside #go-up.show-percent .scroll-percent+i,#rightside #go-up:hover .scroll-percent{display:none}#rightside #go-up:hover .scroll-percent+i{display:block}#sidebar #menu-mask{position:fixed;z-index:102;display:none;width:100%;height:100%;background:rgba(0,0,0,.8)}#sidebar #sidebar-menus{position:fixed;top:0;right:-300px;z-index:103;overflow-x:hidden;overflow-y:auto;width:300px;height:100%;background:var(--sidebar-bg);-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;-ms-transition:.5s;transition:.5s}#sidebar #sidebar-menus.open{-webkit-transform:translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0);-o-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}#sidebar #sidebar-menus>.avatar-img{margin:20px auto}#sidebar #sidebar-menus .sidebar-site-data{padding:0 10px}#sidebar #sidebar-menus hr{margin:20px auto}#sidebar #sidebar-menus .menus_items{padding:0 10px 40px}#sidebar #sidebar-menus .menus_items .site-page{position:relative;display:block;padding:6px 30px 6px 22px;color:var(--font-color);font-size:1.15em}#sidebar #sidebar-menus .menus_items .site-page:hover{background:var(--text-bg-hover)}#sidebar #sidebar-menus .menus_items .site-page i:first-child{width:15%;text-align:left}#sidebar #sidebar-menus .menus_items .site-page.group>i:last-child{position:absolute;top:.78em;right:18px;-webkit-transition:-webkit-transform .3s;-moz-transition:-moz-transform .3s;-o-transition:-o-transform .3s;-ms-transition:-ms-transform .3s;transition:transform .3s}#sidebar #sidebar-menus .menus_items .site-page.group.hide>i:last-child{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}#sidebar #sidebar-menus .menus_items .site-page.group.hide+.menus_item_child{display:none}#sidebar #sidebar-menus .menus_items .menus_item_child{margin:0;list-style:none}#vcomment{font-size:1.1em}#vcomment .vbtn{border:none;background:var(--btn-bg);color:var(--btn-color)}#vcomment .vbtn:hover{background:var(--btn-hover-color)}#vcomment .vimg{-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}#vcomment .vimg:hover{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}#vcomment .vcards .vcard .vcontent.expand:after,#vcomment .vcards .vcard .vcontent.expand:before{z-index:22}#waline-wrap,.ispeak-comment{--waline-font-size:1.1em;--waline-theme-color:#8fbc8f;--waline-active-color:#ff7242}#waline-wrap .wl-comment-actions>button:not(last-child),.ispeak-comment .wl-comment-actions>button:not(last-child){padding-right:4px}#vcomment textarea{background:url("https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/comments/bg.jpg") 100% 100% no-repeat}#vcomment textarea:focus{background-image:none}.fireworks{position:fixed;top:0;left:0;z-index:9999;pointer-events:none}.medium-zoom-image--opened{z-index:99999!important;margin:0!important}.medium-zoom-overlay{z-index:99999!important}.mermaid-wrap{margin:0 0 20px;text-align:center}.mermaid-wrap>svg{height:100%}.fb-comments iframe,.utterances{width:100%!important}#gitalk-container .gt-meta{margin:0 0 .8em;padding:6px 0 16px}.katex-wrap{overflow:auto}.katex-wrap::-webkit-scrollbar{display:none}mjx-container{overflow-x:auto;overflow-y:hidden;padding-bottom:4px;max-width:100%}mjx-container[display]{display:block!important;min-width:auto!important}mjx-container:not([display]){display:inline-grid!important}mjx-assistive-mml{right:0;bottom:0}.aplayer{color:#4c4948}#article-container .aplayer{margin:0 0 20px}#article-container .aplayer ol,#article-container .aplayer ul{margin:0;padding:0}#article-container .aplayer ol li,#article-container .aplayer ul li{margin:0;padding:0 15px}#article-container .aplayer ol li:before,#article-container .aplayer ul li:before{content:none}.snackbar-css{border-radius:5px!important}.abc-music-sheet{margin:0 0 20px;opacity:0;-webkit-transition:opacity .3s;-moz-transition:opacity .3s;-o-transition:opacity .3s;-ms-transition:opacity .3s;transition:opacity .3s}.abc-music-sheet.abcjs-container{opacity:1;-ms-filter:none;filter:none}@media screen and (max-width:768px){.fancybox__toolbar__column.is-middle{display:none}}#article-container .btn-center{margin:0 0 20px;text-align:center}#article-container .btn-beautify{display:inline-block;margin:0 4px 6px;padding:0 15px;background-color:var(--btn-beautify-color,#777);color:#fff;line-height:2}#article-container .btn-beautify.blue{--btn-beautify-color:#428bca}#article-container .btn-beautify.pink{--btn-beautify-color:#ff69b4}#article-container .btn-beautify.red{--btn-beautify-color:#f00}#article-container .btn-beautify.purple{--btn-beautify-color:#6f42c1}#article-container .btn-beautify.orange{--btn-beautify-color:#ff8c00}#article-container .btn-beautify.green{--btn-beautify-color:#5cb85c}#article-container .btn-beautify:hover{background-color:var(--btn-hover-color);text-decoration:none}#article-container .btn-beautify i+span{margin-left:6px}#article-container .btn-beautify:not(.block)+.btn-beautify:not(.block){margin:0 4px 20px}#article-container .btn-beautify.block{display:block;margin:0 0 20px;width:fit-content;width:-moz-fit-content}#article-container .btn-beautify.block.center{margin:0 auto 20px}#article-container .btn-beautify.block.right{margin:0 0 20px auto}#article-container .btn-beautify.larger{padding:6px 15px}#article-container .btn-beautify.outline{border:1px solid transparent;border-color:var(--btn-beautify-color,#777);background-color:transparent;color:var(--btn-beautify-color,#777)}#article-container .btn-beautify.outline:hover{background-color:var(--btn-beautify-color,#777);color:#fff!important}#article-container figure.gallery-group{position:relative;float:left;overflow:hidden;margin:6px 4px;width:calc(50% - 8px);height:250px;border-radius:8px;background:#000;-webkit-transform:translate3d(0,0,0)}@media screen and (max-width:600px){.relatedPosts>.relatedPosts-list>div{width:calc(100% - 4px)}#article-container figure.gallery-group{width:calc(100% - 8px)}}#article-container figure.gallery-group:hover img{opacity:.4;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group:hover .gallery-group-name::after{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group:hover p{opacity:1;-ms-filter:none;filter:none;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#article-container figure.gallery-group img{position:relative;margin:0;max-width:none;width:calc(100% + 20px);height:250px;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;opacity:.8;-webkit-transition:.3s,filter 375ms ease-in .2s;-moz-transition:.3s,filter 375ms ease-in .2s;-o-transition:.3s,filter 375ms ease-in .2s;-ms-transition:.3s,filter 375ms ease-in .2s;transition:.3s,filter 375ms ease-in .2s;-webkit-transform:translate3d(-10px,0,0);-moz-transform:translate3d(-10px,0,0);-o-transform:translate3d(-10px,0,0);-ms-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0);object-fit:cover}#article-container figure.gallery-group figcaption{position:absolute;top:0;left:0;padding:30px;width:100%;height:100%;color:#fff;text-transform:uppercase;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}#article-container figure.gallery-group figcaption>a{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1000;opacity:0}#article-container figure.gallery-group p{margin:0;padding:8px 0 0;letter-spacing:1px;font-size:1.1em;line-height:1.5;opacity:0;-webkit-transition:opacity .35s,-webkit-transform .35s;-moz-transition:opacity .35s,-moz-transform .35s;-o-transition:opacity .35s,-o-transform .35s;-ms-transition:opacity .35s,-ms-transform .35s;transition:opacity .35s,transform .35s;-webkit-transform:translate3d(100%,0,0);-moz-transform:translate3d(100%,0,0);-o-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);-webkit-line-clamp:4}#article-container figure.gallery-group .gallery-group-name{position:relative;margin:0;padding:8px 0;font-weight:700;font-size:1.65em;line-height:1.5;-webkit-line-clamp:2}#article-container figure.gallery-group .gallery-group-name:after{position:absolute;bottom:0;left:0;width:100%;height:2px;background:#fff;content:'';-webkit-transition:-webkit-transform .35s;-moz-transition:-moz-transform .35s;-o-transition:-o-transform .35s;-ms-transition:-ms-transform .35s;transition:transform .35s;-webkit-transform:translate3d(-100%,0,0);-moz-transform:translate3d(-100%,0,0);-o-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}#article-container .gallery-group-main{overflow:auto;padding:0 0 16px}#article-container .gallery{margin:0 0 16px;text-align:center}#article-container .gallery .fj-gallery{opacity:0}#article-container .gallery .fj-gallery .img-alt{display:none}#article-container .gallery .fj-gallery.lazyload+button{display:inline-block}#article-container .gallery .fj-gallery .gallery-data{display:none}#article-container .gallery button{display:none;margin-top:25px;padding:10px;width:9em;border-radius:5px;background:var(--btn-bg);color:var(--btn-color);font-weight:700;font-size:1.1em;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s}#article-container .gallery button>*{-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#article-container .gallery button i{width:0;opacity:0}#article-container .gallery button:hover{background:var(--btn-hover-color)}#article-container .gallery button:hover i{margin-left:2px;width:20px;opacity:1;-ms-filter:none;filter:none}blockquote.pullquote{position:relative;max-width:45%;font-size:110%}blockquote.pullquote.left{float:left;margin:1em .5em 0 0}blockquote.pullquote.right{float:right;margin:1em 0 0 .5em}.video-container{position:relative;overflow:hidden;margin-bottom:16px;padding-top:56.25%;height:0}.video-container iframe{position:absolute;top:0;left:0;margin-top:0;width:100%;height:100%}.hide-block>.hide-button,.hide-inline>.hide-button{display:inline-block;padding:5px 18px;background:#8fbc8f;color:var(--white)}.hide-block>.hide-button:hover,.hide-inline>.hide-button:hover{background-color:var(--btn-hover-color)}.hide-block>.hide-button.open,.hide-inline>.hide-button.open{display:none}.hide-block>.hide-button.open+div,.hide-inline>.hide-button.open+div{display:block}.hide-block>.hide-button.open+span,.hide-inline>.hide-button.open+span{display:inline}.hide-block>.hide-content,.hide-inline>.hide-content{display:none}.hide-inline>.hide-button,.hide-inline>.hide-content{margin:0 6px}.hide-block{margin:0 0 16px}.toggle{margin-bottom:20px;border:1px solid #f0f0f0}.toggle>.toggle-button{padding:6px 15px;background:#f0f0f0;color:#1f2d3d;cursor:pointer}.toggle>.toggle-content{margin:30px 24px}#article-container .inline-img{display:inline;margin:0 3px;height:1.1em;vertical-align:text-bottom}.hl-label{padding:2px 4px;border-radius:3px;color:#fff}.hl-label.default{background-color:#777}.hl-label.blue{background-color:#428bca}.hl-label.pink{background-color:#ff69b4}.hl-label.red{background-color:red}.hl-label.purple{background-color:#6f42c1}.hl-label.orange{background-color:#ff8c00}.hl-label.green{background-color:#5cb85c}.note{position:relative;margin:0 0 20px;padding:15px;border-radius:3px}.note.icon-padding{padding-left:3em}.note>.note-icon{position:absolute;top:calc(50% - .5em);left:.8em;font-size:larger}.note.blue:not(.disabled){border-left-color:#428bca!important}.note.blue:not(.disabled).modern{border-left-color:transparent!important;color:#428bca}.note.blue:not(.disabled):not(.simple){background:#e3eef7!important}.note.blue>.note-icon{color:#428bca}.note.pink:not(.disabled){border-left-color:#ff69b4!important}.note.pink:not(.disabled).modern{border-left-color:transparent!important;color:#ff69b4}.note.pink:not(.disabled):not(.simple){background:#ffe9f4!important}.note.pink>.note-icon{color:#ff69b4}.note.red:not(.disabled){border-left-color:red!important}.note.red:not(.disabled).modern{border-left-color:transparent!important;color:red}.note.red:not(.disabled):not(.simple){background:#ffd9d9!important}.note.red>.note-icon{color:red}.note.purple:not(.disabled){border-left-color:#6f42c1!important}.note.purple:not(.disabled).modern{border-left-color:transparent!important;color:#6f42c1}.note.purple:not(.disabled):not(.simple){background:#e9e3f6!important}.note.purple>.note-icon{color:#6f42c1}.note.orange:not(.disabled){border-left-color:#ff8c00!important}.note.orange:not(.disabled).modern{border-left-color:transparent!important;color:#ff8c00}.note.orange:not(.disabled):not(.simple){background:#ffeed9!important}.note.orange>.note-icon{color:#ff8c00}.note.green:not(.disabled){border-left-color:#5cb85c!important}.note.green:not(.disabled).modern{border-left-color:transparent!important;color:#5cb85c}.note.green:not(.disabled):not(.simple){background:#e7f4e7!important}.note.green>.note-icon{color:#5cb85c}.note.simple{border:1px solid #eee;border-left-width:5px}.note.modern{border:1px solid transparent!important;background-color:#f5f5f5;color:#4c4948}.note.flat{border:initial;border-left:5px solid #eee;background-color:#f9f9f9;color:#4c4948}.note h2,.note h3,.note h4,.note h5,.note h6{margin-top:3px;margin-bottom:0;padding-top:0!important;border-bottom:initial}.note blockquote:first-child,.note img:first-child,.note ol:first-child,.note p:first-child,.note pre:first-child,.note table:first-child,.note ul:first-child{margin-top:0!important}.note blockquote:last-child,.note img:last-child,.note ol:last-child,.note p:last-child,.note pre:last-child,.note table:last-child,.note ul:last-child{margin-bottom:0!important}.note:not(.no-icon){padding-left:3em}.note:not(.no-icon)::before{position:absolute;top:calc(50% - .95em);left:.8em;font-size:larger}.note.default.flat{background:#f7f7f7}.note.default.modern{border-color:#e1e1e1;background:#f3f3f3;color:#666}.note.default.modern a:not(.btn){color:#666}.note.default.modern a:not(.btn):hover{color:#454545}.note.default:not(.modern){border-left-color:#777}.note.default:not(.modern) h2,.note.default:not(.modern) h3,.note.default:not(.modern) h4,.note.default:not(.modern) h5,.note.default:not(.modern) h6{color:#777}.note.default:not(.no-icon)::before{content:'\f0a9'}.note.default:not(.no-icon):not(.modern)::before{color:#777}.note.primary.flat{background:#f5f0fa}.note.primary.modern{border-color:#e1c2ff;background:#f3daff;color:#6f42c1}.note.primary.modern a:not(.btn){color:#6f42c1}.note.primary.modern a:not(.btn):hover{color:#453298}.note.primary:not(.modern){border-left-color:#6f42c1}.note.primary:not(.modern) h2,.note.primary:not(.modern) h3,.note.primary:not(.modern) h4,.note.primary:not(.modern) h5,.note.primary:not(.modern) h6{color:#6f42c1}.note.primary:not(.no-icon)::before{content:'\f055'}.note.primary:not(.no-icon):not(.modern)::before{color:#6f42c1}.note.info.flat{background:#eef7fa}.note.info.modern{border-color:#b3e5ef;background:#d9edf7;color:#31708f}.note.info.modern a:not(.btn){color:#31708f}.note.info.modern a:not(.btn):hover{color:#215761}.note.info:not(.modern){border-left-color:#428bca}.note.info:not(.modern) h2,.note.info:not(.modern) h3,.note.info:not(.modern) h4,.note.info:not(.modern) h5,.note.info:not(.modern) h6{color:#428bca}.note.info:not(.no-icon)::before{content:'\f05a'}.note.info:not(.no-icon):not(.modern)::before{color:#428bca}.note.success.flat{background:#eff8f0}.note.success.modern{border-color:#d0e6be;background:#dff0d8;color:#3c763d}.note.success.modern a:not(.btn){color:#3c763d}.note.success.modern a:not(.btn):hover{color:#32562c}.note.success:not(.modern){border-left-color:#5cb85c}.note.success:not(.modern) h2,.note.success:not(.modern) h3,.note.success:not(.modern) h4,.note.success:not(.modern) h5,.note.success:not(.modern) h6{color:#5cb85c}.note.success:not(.no-icon)::before{content:'\f058'}.note.success:not(.no-icon):not(.modern)::before{color:#5cb85c}.note.warning.flat{background:#fdf8ea}.note.warning.modern{border-color:#fae4cd;background:#fcf4e3;color:#8a6d3b}.note.warning.modern a:not(.btn){color:#8a6d3b}.note.warning.modern a:not(.btn):hover{color:#714f30}.note.warning:not(.modern){border-left-color:#f0ad4e}.note.warning:not(.modern) h2,.note.warning:not(.modern) h3,.note.warning:not(.modern) h4,.note.warning:not(.modern) h5,.note.warning:not(.modern) h6{color:#f0ad4e}.note.warning:not(.no-icon)::before{content:'\f06a'}.note.warning:not(.no-icon):not(.modern)::before{color:#f0ad4e}.note.danger.flat{background:#fcf1f2}.note.danger.modern{border-color:#ebcdd2;background:#f2dfdf;color:#a94442}.note.danger.modern a:not(.btn){color:#a94442}.note.danger.modern a:not(.btn):hover{color:#84333f}.note.danger:not(.modern){border-left-color:#d9534f}.note.danger:not(.modern) h2,.note.danger:not(.modern) h3,.note.danger:not(.modern) h4,.note.danger:not(.modern) h5,.note.danger:not(.modern) h6{color:#d9534f}.note.danger:not(.no-icon)::before{content:'\f056'}.note.danger:not(.no-icon):not(.modern)::before{color:#d9534f}#article-container .tabs{position:relative;margin:0 0 20px;border-right:1px solid var(--tab-border-color);border-bottom:1px solid var(--tab-border-color);border-left:1px solid var(--tab-border-color)}#article-container .tabs>.nav-tabs{display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:box;display:flex;-webkit-box-lines:multiple;-moz-box-lines:multiple;-o-box-lines:multiple;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0;background:var(--tab-botton-bg)}#article-container .tabs>.nav-tabs>.tab{margin:0;padding:0;list-style:none}#article-container .tabs>.nav-tabs>.tab button{display:block;padding:8px 18px;width:100%;border-top:2px solid var(--tab-border-color);background:var(--tab-botton-bg);color:var(--tab-botton-color);line-height:2;-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;-ms-transition:.4s;transition:.4s}#article-container .tabs>.nav-tabs>.tab button i{width:1.5em}#article-container .tabs>.nav-tabs>.tab.active button{border-top:2px solid #8fbc8f;background:var(--tab-button-active-bg);cursor:default}#article-container .tabs>.nav-tabs>.tab:not(.active) button:hover{border-top:2px solid var(--tab-button-hover-bg);background:var(--tab-button-hover-bg)}#article-container .tabs>.tab-contents .tab-item-content{position:relative;display:none;padding:36px 24px}@media screen and (max-width:768px){#article-container .tabs>.nav-tabs>.tab{-webkit-box-flex:1;-moz-box-flex:1;-o-box-flex:1;-ms-box-flex:1;box-flex:1;-webkit-flex-grow:1;flex-grow:1}#article-container .tabs>.tab-contents .tab-item-content{padding:24px 14px}}#article-container .tabs>.tab-contents .tab-item-content.active{display:block;-webkit-animation:.5s tabshow;-moz-animation:.5s tabshow;-o-animation:.5s tabshow;-ms-animation:tabshow 0.5s;animation:.5s tabshow}#article-container .tabs .tab-to-top{position:absolute;right:15px;display:block;color:#99a9bf}@-moz-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-o-keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@keyframes tabshow{0%{-webkit-transform:translateY(15px);-moz-transform:translateY(15px);-o-transform:translateY(15px);-ms-transform:translateY(15px);transform:translateY(15px)}100%{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}#article-container .timeline{margin:0 0 20px 10px;padding:14px 20px 5px;border-left:2px solid var(--timeline-color,#8fbc8f)}#article-container .timeline.blue{--timeline-color:#428bca;--timeline-bg:rgba(66,139,202, 0.2)}#article-container .timeline.pink{--timeline-color:#ff69b4;--timeline-bg:rgba(255,105,180, 0.2)}#article-container .timeline.red{--timeline-color:#f00;--timeline-bg:rgba(255,0,0, 0.2)}#article-container .timeline.purple{--timeline-color:#6f42c1;--timeline-bg:rgba(111,66,193, 0.2)}#article-container .timeline.orange{--timeline-color:#ff8c00;--timeline-bg:rgba(255,140,0, 0.2)}#article-container .timeline.green{--timeline-color:#5cb85c;--timeline-bg:rgba(92,184,92, 0.2)}#article-container .timeline .timeline-item{margin:0 0 15px}#article-container .timeline .timeline-item:hover .item-circle:before{border-color:var(--timeline-color,#8fbc8f)}#article-container .timeline .timeline-item.headline .timeline-item-title .item-circle>p{font-weight:600;font-size:1.2em}#article-container .timeline .timeline-item.headline .timeline-item-title .item-circle:before{left:-28px;border:4px solid var(--timeline-color,#8fbc8f)}#article-container .timeline .timeline-item.headline:hover .item-circle:before{border-color:var(--pseudo-hover)}#article-container .timeline .timeline-item .timeline-item-title{position:relative}#article-container .timeline .timeline-item .item-circle:before{position:absolute;top:50%;left:-27px;width:6px;height:6px;border:3px solid var(--pseudo-hover);border-radius:50%;background:var(--card-bg);content:'';-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;-ms-transition:.3s;transition:.3s;-webkit-transform:translate(0,-50%);-moz-transform:translate(0,-50%);-o-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%)}#article-container .timeline .timeline-item .item-circle>p{margin:0 0 8px;font-weight:500}#article-container .timeline .timeline-item .timeline-item-content{position:relative;padding:12px 15px;border-radius:8px;background:var(--timeline-bg,#eef5ee);font-size:.93em}#article-container .timeline .timeline-item .timeline-item-content>:last-child{margin-bottom:0}#article-container .timeline+.timeline{margin-top:-20px}[data-theme=dark]{--docsearch-primary-color:#5468ff!important;--docsearch-logo-color:#5468ff!important;--global-bg:#0d0d0d;--font-color:rgba(255,255,255,0.7);--hr-border:rgba(255,255,255,0.4);--hr-before-color:rgba(255,255,255,0.7);--search-bg:#121212;--search-input-color:rgba(255,255,255,0.7);--search-a-color:rgba(255,255,255,0.7);--preloader-bg:#0d0d0d;--preloader-color:rgba(255,255,255,0.7);--tab-border-color:#2c2c2c;--tab-botton-bg:#2c2c2c;--tab-botton-color:rgba(255,255,255,0.7);--tab-button-hover-bg:#383838;--tab-button-active-bg:#121212;--card-bg:#121212;--sidebar-bg:#121212;--btn-hover-color:#787878;--btn-color:rgba(255,255,255,0.7);--btn-bg:#1f1f1f;--text-bg-hover:#383838;--light-grey:rgba(255,255,255,0.7);--dark-grey:rgba(255,255,255,0.2);--white:rgba(255,255,255,0.9);--text-highlight-color:rgba(255,255,255,0.9);--blockquote-color:rgba(255,255,255,0.7);--blockquote-bg:#2c2c2c;--reward-pop:#2c2c2c;--toc-link-color:rgba(255,255,255,0.6);--hl-color:rgba(255,255,255,0.7);--hl-bg:#171717;--hltools-bg:#1a1a1a;--hltools-color:#90a4ae;--hlnumber-bg:#171717;--hlnumber-color:rgba(255,255,255,0.4);--hlscrollbar-bg:#1f1f1f;--hlexpand-bg:linear-gradient(180deg, rgba(23,23,23,0.6), rgba(23,23,23,0.9));--scrollbar-color:#1f1f1f;--timeline-bg:#1f1f1f;--zoom-bg:#121212;--mark-bg:rgba(0,0,0,0.6)}[data-theme=dark] #web_bg:before{position:absolute;width:100%;height:100%;background-color:rgba(0,0,0,.7);content:''}[data-theme=dark] #article-container code{background:#2c2c2c}[data-theme=dark] #article-container pre>code{background:#171717}[data-theme=dark] #article-container figure.highlight{-webkit-box-shadow:none;box-shadow:none}[data-theme=dark] #article-container .note code{background:rgba(27,31,35,.05)}[data-theme=dark] #article-container .aplayer{filter:brightness(.8)}[data-theme=dark] #page-header.nav-fixed>#nav,[data-theme=dark] #page-header.not-top-img>#nav{background:rgba(18,18,18,.8);-webkit-box-shadow:0 5px 6px -5px rgba(133,133,133,0);box-shadow:0 5px 6px -5px rgba(133,133,133,0)}[data-theme=dark] #post-comment #comment-switch{background:#2c2c2c!important}[data-theme=dark] #article-container iframe,[data-theme=dark] #post-comment #comment-switch .switch-btn,[data-theme=dark] .ads-wrap,[data-theme=dark] .btn-beautify,[data-theme=dark] .error-img,[data-theme=dark] .gist,[data-theme=dark] .hide-button,[data-theme=dark] .hl-label,[data-theme=dark] .note,[data-theme=dark] .post-outdate-notice{filter:brightness(.8)}[data-theme=dark] img{filter:blur(0) brightness(.8)}[data-theme=dark] #aside-content .aside-list>.aside-list-item:not(:last-child){border-bottom:1px dashed rgba(255,255,255,.1)}[data-theme=dark] #gitalk-container{filter:brightness(.8)}[data-theme=dark] #gitalk-container svg{fill:rgba(255,255,255,0.9)!important}[data-theme=dark] #disqusjs #dsqjs .dsqjs-no-comment,[data-theme=dark] #disqusjs #dsqjs .dsqjs-tab-active,[data-theme=dark] #disqusjs #dsqjs:focus,[data-theme=dark] #disqusjs #dsqjs:hover{color:rgba(255,255,255,.7)}[data-theme=dark] #disqusjs #dsqjs .dsqjs-order-label{background-color:#1f1f1f}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body{color:rgba(255,255,255,.7)}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body code,[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body pre{background:#2c2c2c}[data-theme=dark] #disqusjs #dsqjs .dsqjs-post-body blockquote{color:rgba(255,255,255,.7)}[data-theme=dark] #artitalk_main #lazy,[data-theme=dark] #operare_artitalk .c2{background:#121212}.read-mode{--font-color:#4c4948;--readmode-light-color:#fff;--white:#4c4948;--light-grey:#4c4948;--gray:#d6dbdf;--hr-border:#d6dbdf;--hr-before-color:#b9c2c9;--highlight-bg:#f7f7f7;--exit-btn-bg:#c0c0c0;--exit-btn-color:#fff;--exit-btn-hover:#8d8d8d;--pseudo-hover:none;background:var(--readmode-light-color)}[data-theme=dark] .read-mode{--font-color:rgba(255,255,255,0.7);--readmode-light-color:#0d0d0d;--white:rgba(255,255,255,0.9);--light-grey:rgba(255,255,255,0.7);--gray:rgba(255,255,255,0.7);--hr-border:rgba(255,255,255,0.5);--hr-before-color:rgba(255,255,255,0.7);--highlight-bg:#171717;--exit-btn-bg:#1f1f1f;--exit-btn-color:rgba(255,255,255,0.9);--exit-btn-hover:#525252}.read-mode .exit-readmode{position:fixed;top:30px;right:30px;z-index:100;width:40px;height:40px;border-radius:8px;background:var(--exit-btn-bg);color:var(--exit-btn-color);font-size:16px;-webkit-transition:background .3s;-moz-transition:background .3s;-o-transition:background .3s;-ms-transition:background .3s;transition:background .3s}.read-mode .exit-readmode:hover{background:var(--exit-btn-hover)}.read-mode #aside-content{display:none}.read-mode #page-header.post-bg{background:0 0!important}.read-mode #page-header.post-bg:before{opacity:0}.read-mode #page-header.post-bg>#post-info{text-align:center}.read-mode #post{margin:0 auto;background:0 0;-webkit-box-shadow:none;box-shadow:none}.read-mode #post:hover{-webkit-box-shadow:none;box-shadow:none}.read-mode #footer,.read-mode #nav,.read-mode #post>:not(#post-info):not(.post-content),.read-mode #rightside,.read-mode #web_bg,.read-mode .highlight-tools,.read-mode .not-top-img,.read-mode .post-outdate-notice,.read-mode>canvas{display:none!important}.read-mode #article-container a{color:#99a9bf}.read-mode #article-container .highlight:not(.js-file-line-container),.read-mode #article-container pre{background:var(--highlight-bg)!important}.read-mode #article-container .highlight:not(.js-file-line-container) *,.read-mode #article-container pre *{color:var(--font-color)!important}.read-mode #article-container figure.highlight{border-radius:0!important;-webkit-box-shadow:none!important;box-shadow:none!important}.read-mode #article-container figure.highlight>:not(.highlight-tools){display:block!important}.read-mode #article-container figure.highlight .line:before{color:var(--font-color)!important}.read-mode #article-container figure.highlight .hljs{background:var(--highlight-bg)!important}.read-mode #article-container h1,.read-mode #article-container h2,.read-mode #article-container h3,.read-mode #article-container h4,.read-mode #article-container h5,.read-mode #article-container h6{padding:0}.read-mode #article-container h1:before,.read-mode #article-container h2:before,.read-mode #article-container h3:before,.read-mode #article-container h4:before,.read-mode #article-container h5:before,.read-mode #article-container h6:before{content:''}.read-mode #article-container h1:hover,.read-mode #article-container h2:hover,.read-mode #article-container h3:hover,.read-mode #article-container h4:hover,.read-mode #article-container h5:hover,.read-mode #article-container h6:hover{padding:0}.read-mode #article-container li:hover:before,.read-mode #article-container ol:hover:before,.read-mode #article-container ul:hover:before{-webkit-transform:none!important;-moz-transform:none!important;-o-transform:none!important;-ms-transform:none!important;transform:none!important}.read-mode #article-container li:before,.read-mode #article-container ol:before{background:0 0!important;color:var(--font-color)!important}.read-mode #article-container ul>li:before{border-color:var(--gray)!important}.read-mode #article-container .tabs{border:2px solid var(--tab-border-color)}.read-mode #article-container .tabs>.nav-tabs{background:0 0}.read-mode #article-container .tabs>.nav-tabs>.tab{border-bottom:0}.read-mode #article-container .tabs>.nav-tabs>.tab button{border-top:none!important;background:0 0}.read-mode #article-container .tabs>.nav-tabs>.tab button:hover{background:0 0!important}.read-mode #article-container .tabs>.nav-tabs>.tab.active button{text-decoration:underline}.read-mode #article-container .tabs>.tab-contents .tab-item-content.active{-webkit-animation:none;-moz-animation:none;-o-animation:none;-ms-animation:none;animation:none}.read-mode #article-container code{color:var(--font-color)}.read-mode #article-container blockquote{border-color:var(--gray);background-color:var(--readmode-light-color)}.read-mode #article-container .hide-toggle{border:1px solid var(--gray)!important}.read-mode #article-container .btn-beautify,.read-mode #article-container .hide-button,.read-mode #article-container .hl-label{border:1px solid var(--gray)!important;background:var(--readmode-light-color)!important;color:var(--font-color)!important}.read-mode #article-container .note{border:2px solid var(--gray);border-left-color:var(--gray)!important;filter:none;background-color:var(--readmode-light-color)!important;color:var(--font-color)}.read-mode #article-container .note .note-icon,.read-mode #article-container .note:before{color:var(--font-color)}.search-dialog{position:fixed;top:10%;left:50%;z-index:1001;display:none;margin-left:-300px;padding:20px;width:600px;border-radius:8px;background:var(--search-bg);--search-height:100vh}@media screen and (max-width:768px){.read-mode .exit-readmode{top:initial;bottom:30px}.search-dialog{top:0;left:0;margin:0;width:100%;height:100%;border-radius:0}}.search-dialog .search-nav{margin:0 0 14px;color:#8fbc8f;font-size:1.4em;line-height:1}.search-dialog .search-nav .search-dialog-title{margin-right:10px}.search-dialog .search-nav .search-close-button{float:right;color:#858585;-webkit-transition:color .2s ease-in-out;-moz-transition:color .2s ease-in-out;-o-transition:color .2s ease-in-out;-ms-transition:color .2s ease-in-out;transition:color .2s ease-in-out}.search-dialog .search-nav .search-close-button:hover{color:#8fbc8f}.search-dialog hr{margin:20px auto}#search-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:none;background:rgba(0,0,0,.6)} \ No newline at end of file diff --git a/css/var.css b/css/var.css new file mode 100644 index 000000000..e69de29bb diff --git a/essay/index.html b/essay/index.html new file mode 100644 index 000000000..5a90b8b23 --- /dev/null +++ b/essay/index.html @@ -0,0 +1,19 @@ +短文 | CC的部落格

短文

ipseak加载中
\ No newline at end of file diff --git a/essay/speak/index.html b/essay/speak/index.html new file mode 100644 index 000000000..ede825b0f --- /dev/null +++ b/essay/speak/index.html @@ -0,0 +1,21 @@ +短文 | CC的部落格

短文

查看全部
\ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e28cc3fb0c628bbf876a5bf7e42f15d24e59d445 GIT binary patch literal 18092 zcmeEtWm6noxb5IhkOX%P!QI{665QQggS$JyB?J!ycXwxScXxL`{ocC2;e0w!6jLx& zG~IizXW0gUAb`*RJ|I9OpcDxZ2n%=}p`;**f{2F*yhM?f5>xr_xBq>?!vf!QoJ!0< zAPHS*G2!nX%V*i{9t8bQgMzhQ?Ir8dDK<+^jNgN*yV;CqyhzYU;?YD%ghZsJ;7Riu zK>@_<6v;|Zd6*bK*$toua8_F>HQ#1ki%)nv1@B#Is`kDunQwUKz!7mtd$rcGZlrr2 z(2MxCSBm8+nNTjrc0h!PRPQK3{#G(!mH~Z^q?17K7fI;<3ZeA128R-aD2|m6EtEH8 zlnna%Su+{~6haoI{C{u$-@Y3IHTm|x6)gjpU25eI=DaZ&c zqUV&&UpUEB7M9SU-fa?5d;=!kbTaMCSyVth=s`M{X@d1}`n9CICm5Xb zm;}ddL6Auf$YOFbV>3|uTWNWeq114$uU-!dHVTJ2e$){7QaN*iQczp)CDXo#BP3*2(zCPdL3B6+?S{Z6qu8wN_O%EF;_t6^5RspG9R9 z1poM#dbKoO@&t;Pk!N|{S&5(r)x8%{y^B6vU3dL3jV3%l)klwyKlxne*5a}3NW$C* zH?`JC(YDkODM)2jE9vX;(r|)G!fFe`FhYA`+&7zS6z z@DT+R6V_XQh@Tx>Zt1aP(|;~p1yf)tz9l_>Jais!7BBo@vX?Houo5WXzdZff!$o~)1YW3A)Y+RSz+rXv%qbQ%zH`MFH*=D2^H_P?3ZQR2Xq<9b*~ zeOW?val!2{@jHvR)uRSH`KofV9`Z_#!ok#w@Q5a=81s-z^l1BuC4DAy$ME8H8)-k6 zePtMerc|#J8_AFLI<3Y?0z!s60`ph6PZJenQR+_}sr(>TBKKPIU#l{9Av;uAY( zRU(LmBKvkp$q@O{bp1X43cBC+_AVw4t;$7>*w-5EI<|Q za=SvrKasDhWKmes)#FM1^7z8ui^DTC0Q_qQ8{dbcF6tBQ!rw(K2+pnde(sQma;V2A z^OH@coa|Jd#hcI#C6jqJbc`!gsfd(D|}Bvwu@_+TJoF4?lLX*j4#}JDygS z(i(6d2ob28FP?|l9!sUrI2DZurb1y2jbJIasF zjF(DFr*g)HIiv1O32`TsjFm9d{5ySyB>CNrbZ&<`Q5zB#@6a;V%?Ldl+`T*Sw0i!W zh2V*6aWw~hF?PNglYX|J56|_HOcsj=2a~`-0aR%H2WF@V3u{XiJ!8D5xmu_hP zUC6qOd&f9C{6VjPoRkWf*_dZlnkphaX7 zQK=bUPj`-{VX3cD{17$%!P6v&kdQ0K+CL{|ULUY5W(Ncj z3&HDoREDJA1cDaJ17-boi<^c*#lswH5EA76kXkkzD5JZw#H(Im+Osj+Yhr_lQU?mn zKPP0i5)#HE4+kqNynE_$Qxhc0Qdl|M7`y7+DA8wkn+WEj!H0Ta>SVH}l0!PjPibgD zS1mnO`uW)%E~aLnqV$1%6Z zaSkTe4}1H`U2BFo+gS%9iK+?CtiHM#Cq6a*CRG;BdE7I|VUZ13E5C9#G`j!(mHKE1 zfG*Z`sP<#WcJq$TuO-aahK8oQi`g)5=)oQ zRUGqiZU8b>Pym}!%DJ_<4u^NF8>aXX{W;c-@`hR0E_=AO`KoEGL9>cX&Q!Pjz)^W)^kP0uO{0X3(u?-R5-xOR`%NWt$YHt?n_vAJvcn!)h z<*~E&D-S+ReY&cjd%y@-e(iqk=MGwc$@Efs1yBeS^lDg9WYON`BxLALgLt&qy)Hh)WJ3oR#pEo$`aJQo;do2W@9MY`71m&_@CF0+UG7g7I-`$0mQcnFbxPt!QL-Nw0d&{N8 zN!9l)&}7=6vkTJB4QwQ$7aZ*eReE4)6Y2bM6C-A9W}nfLn#mgX?a)h_vD-K)S^>6; z2~FzwG-OtSaK()gue>z&x)B?Hyvlg91j>nfE4~ea*g!=@n`!C5r{0y~srQY2^-+pY z7d;5`)9_BjNm%WR#R4jm4B|cbVw-BE`1FfLmK`lAC1HgQ5hGXhpmr$c@rVuj;uExx zkTn{S1^!^CcNm6~$IrHxZAVm;u^re6_2{t(v!WnH;)&Z+?Q!qs$t=fgx0q4z*FRMT zJFFFxFgxOyDIUlWF3at7aR)Y;gkAoU`qoBQcr$|}8)eQ*xZ+Lx+C(Rvg;EIaf-_w& zwaZ=)a`H+GI0uQH-yMM!L6MZ0OQb&}_|C>wFS4xsg3*20hQrCzx#>S}Ay+9Z7nWDj z+h5xu+Fb0zsTG)h!qeuA;2#goL*edvK0Nv!6s|>h;_=YWRdFO+G5QvYq3Cpg`-)dy z9(nzcnmPUUxCrIUegAt^-rWWw-zM9`h?F9}N=q|?Zt*7^q5S3eG((Pe{sH`T9r-o4 z3GsxR^RuQJ?p7QAH_y8u4(G|kz%O6W!L50Le(h_4b7W1YUlbPZ_uYmCV~$bqfZ4$Gd{>P#z>r_yPCl@Wo?fH!6X5A@Sw5a~@1BoWxjXqAIl{ z)9XHlzLWQqo!>NK7ZSQr1@MKawul+wG}J7?O(D%#47{~NV->Z-!qhlMaV#Ze>2CI< z7J+;7WPw+O9u3ZW2DYNn`s-TKOj#yl zN^q$kuJrnJ@LNt6I&ZbYI-YLKs9_B|isUT`kew@=am(%=nSa`pnP7SiId|Y(XziaL zira_#DF^r@b}5Gn_PP{EK^e*4>keNj1=6|S*W^RwQG8{Yh7@@O54<<3Bf|3VC`l$Oosy-SlQwg#n z9jZ=+4LI)3S=iV2)LTyE1r!yUk3*fG63p;BEz`$`yvdCf3f&^Adi!4;|-w5cES>D`=nPHF4$*nSQN9K@d`y zjVisdoc0U}0xeE9<%a~z`k(b10*vD5eA)a|nr{ioI1v=6NVw!iz@LnM2yLEYkBW#v z^4hLVfX?RT+vd$G)(V}%UFPP2iw9TS_-%|~GpKo~jJsuS@|^&UxnK1JKO57S4z%xoQJeQzJ&O7F-`)evzyn7PyOv}gZk`$q7* zk_#U$Mi~b);z?o;Yna+d{UpaX+z|kybMlUtYy7*m(MBMBIk{bm3}-*aNfw++fcF?` zLYL4`=eEqxx0MSPCET$%Ta^|AsNlQ9+bK^_BUNi`Fr*htHi;OflIaa*xXnAu&Cy5w zTpnwFBoD#&e;QC&%zWxeVM$tJ=OB$OB`C(beq(8)eo{S(Mad|dp zF(D~DUYN$l3sbWkC$5>nnLlMwJ6ijfVLjrXd5v-1`Py&bLH?gV^CZ1iJ3tiIkBM9y zv*6=Oe{Z}}oBDhnE^j7o4QpG&(e?kxacR2l;K_9J>6qQ6Z2t0~&JGjm+y@}ptm_kzvZAf8vf4bVe%o)6=A-?$-oAC+) z;73{3i%SBT$bP0~hbq5K_+e5omqPTK0#@){6^OEaMH;R(FR~v2Q-VMkt8PuJomoiB zf&=SI30M#`Yyx)|GZxF{n9-suxus}@YJq7fe&5k{oKbR$Ln8F zi@Y&_84M^+>|l@ke>vns#Kfvy?_M^7#kqGGlB~|epFch8@e3g^6c7C8lF+9nZ@Zp& zzq(Q%=&5(FiofZzTihhjS=Bq+-U;F=g=)9=CK>+zf zx5D`DS8o5Aq;6W#p3X~$Ow(sd$)ul2|Kec&-Mb-OxA@9y$u+Wpzcm)RlOH^3L6S{k z64M@@qCpJ6!&KE2?b_oIshh9oUt)Spqc_gm5ekiefuj@O_SZL3wnl3&=g4ZUCdZny zSM;F^y345;{Ss$1cZpNqe?kfST0^Bunmef}qs+@$OvF??>G6&`%|~| z$GUMFMhNWJE^{>luz%4pCMzMCAa8YiSS67RFdxLrdS6eU5#Kp$ZC{q=k%JncLRM|k z6->LUa;BYBlqPjXiDMMG#?`}8NWlX5#>H5m8wBXVr;H|!C-lN`Yp;HD^*!W$qKU1x z&tIt;$aiX0mt4;YhfaAi39LqGgBNw_WOpk%Q7|T#&3N8|d-g3h+}omZ2|C#& z<9TCM-+r&g5h#%1IOWUR)^@hS1A&a zZk9cLD)7Q*ikWF8;QM>TAY^Y7^#S~{llRds>u`a|LzjwOjUV{klaRN?v>{wq6a+$( z8~Nl^W=n+$DGS_}uxz3nx~zd9dgCK_+k?rm?{3*%3*!~FFCdeJ1g0S( zUel8_4f?`x5EJb))4Z)bbNZ|zqt}Ng0Qf>(M5u7BaL=AAW zFokJ5cN(Qp-+&)E%V^whQEquvnCPg%cij4{{Fm%3^O(8Wb&DP|f*~uSFDgq7gkUqa zl9Jdffal^F)rnX#1?;?%)yPeyg#?BC_Ay*k+ z?WW*bZ8M`I#KN)`c+#{B;)!}EJbm_NVbrdrRI0Sba(B1vnNP%zr#ywRI6;5R4A3$L z5XU9CNYl6(hmbBFxZbk7yh&f8SJ0bp8!#X)#_bNW1l2F+{-C{kBR%M84tx=07?|J4 z+nnBvqWa{=QB>W z*=PKP+41EJIAHpeUO+8xT%d|xrQx0cTnT(sdddU!*w)Muq19SuQU~6aqty)^M>>q=hy z(lz&r=3x~M7hIP4TI_%SsWZ=ZN~=qb)7R3yO-G($L zo}k$e_2HuL=IR92;$Z^U7& zss$G?mpJMloVV?)eCjnj$?h(;L|^dOXIX8Bt2AUU-%@=&Q8bV&}01 z3!FVsKu_E}sX5BgGwnOTq+c{qxwrJ1V($(qe)K&2B#O&d@?i}sKdN%{abU53EKaQA zj)zYa=?x!9M^77-=XQ2G>i(481R1~I#qGfO31!?78G$?$xzDp*b8fFCma(~$RIG3= z741d!48{@hSt4RJDBjUcHU5X}MfF^7sM>TqIZNmH&aybZgVgY+5>%>T8 zJ%$UDavz!R_QX&v+xQ&~ zGl(g=yJ_~SCIvt|8hIuvu?+f**ncnl|1;D@qC+yMnuTwlPx7G+NYE$IWv;h*>BqD& zSb9;CQNOalQ-Yu(pj&^CW3V^fg6nnOgiz>h5hx*fF#~m(sJITqh&%X@ z1fO^Cj1Yo&8SxVnB%LDHr4U>LxH!tX)YH<>XI3J$AZ$J*CXPJgOqF!g5;rL0hnJ;H zxInwOQ8phod}C;7kGx26E3D-?lPUSq{+HUCPQ)ig5V6H=w{iLM;pC(+6kKd>)OakchaB=Culqi=u$Kl%g|;Sl66IS zhE01$*fe&*A)@>&0*+y8EW9NQHjlGj4#0fXacc1k^JFMmK@`HIFoG3Hn@Z-Ta1+M% z=4ed9tkjUU{&sQ+BooAMKFC3^BzY&XB1gV{q`zwz1_VE5Y_win1Cr4!q%X%lGPpkm zWZs`W_;0X6pYN=T&rbG6VMr@lDnpa}S|bnEEth&|;a{Jy0MY%c=*;x@XS0{I!Tfzh z3Ig`SLpc@f@S6ci+t=F`#0sybSRq-mH?Nf>DXw8CMz-lCQv>M;BV*Z~)s8a}Zirc| z-<@bhiZ7}k)@GWf&|$htKZuRjr1%+#@!r0b|q!}d|IPhL~B?a-r3lNImMZD zhO|3*YG>?+@^56!L47G=VChFE!|(=hfoCO8LC-daz~cOPf2zPY%%h1UgrI>G=r8rm zkhYG;8QXM~Y;bRpf4|ntGY9J8cPf*++UqkQU+wy3dR~4K9WVF`MF%ONbA9`fQLP0H zq%1?6r7GuF!3EXq)iLT5bjhGw@(h1xMY`QSQRj4i!M?dqvsDJBTyM1maSEccfl_kY zE;cWzbF+g@=UXj$+0&`!-Ig0;KDGW86%?!oFwzv1H|oI&7<5?Ohb+7yPiiw5R0|)i zBP}@Y{BvF5q#V93Vi4UG6w**Ygfyo4c{?hE6zgAX6$g9fAg0eo{5Tnoz@kEhq$K=| z#qt+si!-_D`E+1GXf%Br`xm#s?AaqlfL~U$+I}4GbRrVYUQ!ZqyiT9^iap>H#zcWZtHfCmFl4C0f$=gy)pfHzbT!9 zf~L`qV`jYDZ#;s{zn$b?6>T4Dce;h&Ox)+mWU|i?j8B;|4n(ppp&#EB4_CX38~GH=;%dNfTt_IhFLw!ns)u zkwzGB*%F9-Q82Rk36ky6D5Z!q(_z~wAo_%txMpd>!hTdhq8;K7Hb?~A&~0Gx&ae&w z&&pj_AlR>SL4=MJh;xl=;dM}BFo3Mq=_hN4vFnfElMm&=&h=y4OMG3kgSy_Ena;)r zfdSrHUM30xcLRo?DEX861Sf|l7d>isz9k`5?LbV_;k}5Hkt1Y$y0UPGv)=kFKUJ7Y zpRB=usmV1fQs$LjHdd_agxPr%vhx(29%ZPR5)m6CC8Tb^xTx8H#@?fJvw~#y^$ANa zzWm+J|DQwnE^_iPU3B#Mr97JO=+xJBzwb)2_EMwb-jB-E-`NIS=I~)5xyZolxH;BbpDU3sJu#%oR-RR|1coap3 zCJ3`CY12W?nOlF8yf0K-XgVUu9k-h|+KBzBZigg5sHh@IG}t+9g4;VRdpBimpQp~9 z3NU5!Du&D9HtVc)+=XexVXy=~7{t7ohMO0D#3yf#&T*d{iZJku#|;+RYC#8kzR6zb zjD84MU)+&r{KghGepJEt#YzWrajk_ts30~V7uv{(G&;P``$JlFt*TQ0e_u+ z1}2WdSt;JWkVK!wCOn%{!1iD?g!KJJ8b73&C+@wuEtTIsPFVrbnf}P>V6BM&&$OQd zHRo`vK=fwOxeil52L{Nf2(7G*R{=~$QV+rXZm}1NBs<>SnO9gZ_hDUo`O`%qBWL2# z2@dc%!*%RS`#IZxOR)V3aEA=t1p8;OoPT8Wta_8Wulu_Z$zv#n$fCtyH|yyz>35b;ss<}wlK&vq^XhHB?#jL~ z0Trtf!Ff>ij!x@~@B(yeoRd=*k)57L=dXMXyuWic)*B{dsko#r6GWyBR+m6p!?GTw5or!zf?cCg_7 z{c1gxu!#_l^Svgy_x|Qye}v6)eI*TD;oWhZDYo5(((hfH{w3PE`oV)!YB=!+I?+$& zE^MTr&)6EcKgwO;|qmPHIJAwx zV!65EaFd*w3i=FZ#x??oyhLlvJ=f5}uTFRuu16$oxoq(K1UiFn6zEKZm?*?y)Bx51 z3}lbSue#FYrx)$P7(@MTE3d9cWo>emiLJU_DXLCp0kpdE)Vc{nH{r| zYGWA;T;-!V1?{OZm>(Zn>FZ#;8gMZOn{d=SB3kZyR_(*c+Bv&{R={YG`Y+{OZ9iOH z{BZP$jLwhTbXyNyyoL8a$+3wjqKl&;6*n=4)8Y9=OkL3yZ?I0q=6nzKO1#AjyI7Sj9 z;r*UH5r8KnS(_G`%08zokY(H;>W(T7IIjeaV1}LZMsyYh5XK?jcn)26oX|FP-$i;q zvf9krRGZipMqcAx$HS(5f4{L@0S)^jHQFYg8A}f6H>p2l&*xjbTkXcvPoc;ao>id_ zou`@^`W}DdZWL~>-qi_Tw>t1TH0Q;uMt_qm^Z+mePNUFMHLrp(0B zQ!9=d4`=)YwUEIs@O|$E>OWUEN!|c6Coaw(Oj{&6PVbjQu6Dj>4l(%BcIU}UTx{ki zpO)fbc%-+D#3LdtVt8XukEd<>6gx<%*ts;eAlm}?R13OFJr}+#;b5i2Vm-vm(-r#i zlE|XCh0v76rl&tDz}&T4*)2nu=jfY$M+d~^f1b^|mtQ4IZE&}^+C9;UiDsc@&)VK3 z*M66dGq14}oBXZMZ4*+w;WAYzMXJK7lmVSQ!9>l!pXHQ~QUx5aaLWA@RxclpuHC$~ zD^HyVct1lTCH}w?gO5yh(Rly!JMi7(Ode((Qz|0#%GQa&L!421Hbpz&e!<(Dq#eX1 zz^T=VQ=nte)I#5iEk1s7^Gp+a_}0UuYuB3IP?>5-$$>?Gwq0S4H|+*pscpXM5Vpid zBX9eO>PW_xkWJTS^~%h+kydU6O31Jx1Sq|j&nx#4QW9R ziJ;mR{uxbCQf<{Fd6n>^U}Ngxt?~hpK;JJQ6t(gQhw-5LqnZ^gT_#g^P9Xeo=pk)B z#~v5_KPIpP@#ZdThc&x)#zqhCxMG#VnokJIIiexmJpy?iK}$@cbc4tg%) z%BvEtP^V5$o@IZ~xTcnOK#!8O^R3Himi^hl59CUIz9peZ3Rljv5Zt@_+7?Gr7_w)% z?1n#&ZBf)RH^=f3JuXI3c|>6w-)du8BV;iIys;=^I4PF+? zQtoY-zR<^X2}x{^m3CgkyYGl>g`e>pIh%zKL5W@5i0b53FkZ-hoH0oQ!CyxhP)kE* zvn*?V$a`-@+4mm2!vv%I$1wl{Co~q0(oqyuF3;#ss~;~ch}Zvy zf_LlVR+`Ro@5VF-)dlgAH0T5Ki}#(*7-h!(N@_1o6$Vp(tYiuFx^uJrr>X{0JbpG4 z#Y$P>$wM68SF}D=^XNVQX7|YkRwY=VC?24#J#im(p_VT{o3By}p|y7URAo(dS3(2H zM3~xUL+8jWK2ZTpL97b?&fqdXwLmjwI4j^Oh+#w*$l()PLpe(P;$55$WkxRf)b}_s z#vzc6E$64lF%&vF6_y)9n%+{JiKKXSGZOZ1-%aj>`wH#I?<@nj32B2ql+c>O!Yu-= z5!?o4!^WsV!{l-Z!V=SguKZ;Q257=reN*v^Ke_MI7IXr0O&>3(#Bm9c^KGNfZ>|Pb6I&qm7!R&&JdB3}4d_<#LbL=)RDxv3{qwWs0o3?sXV$%|P0jmiJJYxu2DpLU@ zwdJ9aJPto+RGfYI_S+L&9rAch=iN$Yg9i;$=Tab|J}$TuqqqWSw?$g6qw;*DrneeW z0)F-|AbRfyGTW*;GLh1aj0WXHyp?2fgCFv2Yp{~U@uSRe``4?y^#8R;|I8WwJvOFD zVzMg9&JfBH6Pcc_c7@=S?aJ!O$%&QOV8|N<9VWVyA}a&f(7rNn?fImI z&`Y_d!z|Irm>^*YLn_r?4Da$k{zv71R{jcxP2VB}#P*3t-#n%`KiajQMCV5Uf`o{Y zu167_&|iU2ParSLd?|>hO@rxjrvHccfbjPk>E;EPT;H`}{haa(_B62I(jd^M>(KqY zo!D7!I{&%}`|%padfj{&O_uYa&-$r-QHsf?s(`G=GVCC!wOUTNhwbm$s|BIE;7a`Y zCQ#UFI$kw;f0ly^dgGW$gZn-^Fb(Dl4R$wozpYV?CbBwc3UXpjOtgIQY`&=>eSHRh z`*vdVopazPPq=uRq>pyfk_8ndh)KnK^)FFl&3@ke=h(V61o=_ zn5vqRUp8HB`FsV5QeW@VVb6UVNPWE3)2z2rqTrGas+9mY`n#rL_?CK<2=s!Zl$N_v zb2c95n-fzggfmu1T1~2DEshpTB=v^HezUuFiTyEdf!j$6G;R3}6=vd(x&1Dz9=;U1 zZ&ggbO+iO5o-}t$O+Xhm3pHS&u-3p7hqS@ApV=%8s#3O?d^V}yoIhVr|CV{?qNP`G zM*-ru*S$d46STt>D9JNAg05SU&$SgpnAWn!^$ynW!4=gQWw0vn>9g}ExJ!ao zRcQuT1Cq)3Q)#GF)=W%|fdR7*50RP%h5`Aw*{h{S{@PZ?i5^$%WTjos+JRW&t&08he7(mz z*^V8BWi`zX##WP!qh7`8kmykkiqvvuPdJ$Rue2fH<3jh*?DZL7&9cOGPKO;t@2;cp z1E|ggof9X^BO_TDZ4C5#StcyD`ivd6UneRMZoayxQ$neOsETXDwc6T7Jd6&dD0rB1 zB#M-~mCKEo)>76{+?A*u8O%^2R=tPOC?FBIq^daC3A(?b<_Gfi*jOEXEHw%XJQXFG zZ=7>qEU+~JjZ8B+Fa%BM->9orud?*oCZsr7V^`N?0ENeP*H&FZ$Ast4c>Ol@hcjd?c11Z$8V+MWEtB2MGj-G&T4itQuhs@S8?)S~rIwj=$l`%BS<}Xkj zdvva^-Oc}X%)`!i_Wb$zwTW#g<#U~w zVt9A(WB*8Bf=!bs2dIZnA5W(sf3CZk`{k)NJ)I7&;nlH}y*-y`%>oXq&cmOTZ=Rcf z^U6zO?pYvHQkP!@L{{L7eDY{*g{*C2Z_0S*6JK*C>C2+4jBF{gc?~rp#y@BMBdBd* zc-)zg`LE?K?B#jcRB!7<-=HP-)07fgqru5NvGf#rnySiZQ-Scvb}g^m6Kqc%LCgQh ziAj^*mYJE?&%b2qB7d1ljLmA<^E^;!Aem@QTw%K3M$)LGGEzEo6VXq(HM{>UllM z?=0ic;!^Q^L~>7f@rOKFuC=uys{gNJH;q7tHu`?ksG8GJwzU_bE-FpUo!FBtM25J- zbe`w_eZY4I1LCqQS5>=Tsml%E{VE0CFJH7C$GL;j+QPgtcMv;>kql3b0G=5DIyFF^ ziFtM~RfGGH5^;QQopD{uN4Eg4Q7ZS7#2Hs-~2uhjXj3Bg2x@LxjE(T z;jHI2V}`vu&CreEN%o5%zzfim+ASd_*+_mw96XBNa2Y6a+WV|`1D#{zMk}f2W=(VG zLBixwfceV|p2KNjitWI1tnkQMSRyWl=fw)Zg_wQG;vtVq6|j)cW${n%b6NW_fJK_u zXTAsYSv9oK4M)!H&O40YxrwrSbdZ{f2(7<)O;R?h8%oW9xD5Lm%w*5ZgK3u6>gvkM zyOzQrj7JIi{7xLScoXFaPL6xat3jf?iL0g!!qYo9yiUY3?8X$UxxLA;^M z@)035C)D*9v-2IH5p}v0`-GjdeNZHM0=jHrx0y#dU09F@PYu?`E(@jt?W4)jUI&-- zAmx)?ghiELSoN$Qa`MJmYm(ec_U?_Pc5CUONr{-K;2nELm^8q>2J9Oj*t1hEF`n42 zKS(2RD?l^ij#dW5fsH^ua$4ZL|8T`i=}W7g%?lsAnX{4NxO}0`>?f}1w)yyw8ebY< z&;ntG~_M%8_Ij>T| zpIBvUJJ>bUJ?RMU?pHg1m&d&Tp96~Inr1cS0v~?fQO;=*##DUXw#~pS586OhYOi7C z>rr8&NsknqyDoF^e@^L0{r;0rf#5?t2JBP$>swr}Ml;7q6~;=D4tUh9qd9ODYb%8DkMp_%IE zq(chx^p;fpRaL1N1QlaAkoobJkw?HcmBjM*jxck5lHj11aaptGTg}tPRIZx6%EEF8 zltII1U2Foc-M3rCNWg~iT9V8bduG}38?YL!RmLM`^{Za|9t zYznoQW5Z>U&@zC7MK}U`X9BluTfnLtFH#+}1Ow;GY4vj{0Uo}t&(cnjsbq4#EML>5 zdh}PGiV2Yns3F*wD84#vH?vST`OC`qPAf!#zRzMSEBu4F;1?}5WIkY}z!^UKH@Z{3 zOknF^0xBVVCNCki^=``EXN_@uxjU0_v%mpD(DGCmE;avF>mhQzi4?>4>hxP(EeAsMA6o-1B?wwT`P;EG`&#$n6Rme0}rH>L1z%Ie|Rrwzpw0Cq4RIQlyLa_8oh_vuil*3(HQ%2baV zx7@6_PVsg|vKRjaHk#GX%qOf~2au1Yw|8*I{=hz()?A~&Oa!`Wz|c1XjEnn!K-dBE z0KBcBfw@A=0AC5RiW!>kZo>@V{JTv-*BqlTF8iE-ks5JNI9-f@Re`LEA71@Ilw<4O zBt70{KW=3%FQ3dW(TtD6fhdnoGS}R50>la<^d%8$HAXr2~N%6$ZbrTynX($WMM@ z24-u6D@}Vt0U`1*>5B)q(MMKCh^8$%M+Am{2h-*-X9n;i0tpmno1YT0xQPF-s=K|h zB7mcmN#1OYNey6%)))uiq=uLIFuK|ExsYs@lnrZ#pXk@&pNg(2;j z5VQ9~xsAampQinfqoq|Z)#=x%G()=|&ySvbq*Lr1$FvFSu{6(O2wkC*(15nlP{rQ^ z{1OiSOiQI7*gGK)S{xc;fAT273$h|(85_gB0GP6Mi~Bfd9fziA2D7rO0!JG(mA`Bi ze$vv^!(H+)BLFJe2=5P;ywpS)VP?#NUT;Ypdfq@b@nM1ntgrI&*xSE0Kux>m!UNka zb2Gn^m-C4*N-bpA@#OPvhAX-}+P3TXFYdR`ACSK^5mC|?j zGP0{|5FCt8EWgk-p~vFTl|=(51ty>6bC+ZJZp>=a+X~{6!jD67a{X3@1@#cpXr||6 z41&HwEP|>_x-ma&_W^}+^~G-aV@0Y9>7t&=B_5?ro;)F0OqJDRI)0HZaJbdW!bX}2 zI26VjOJ`uy98}#)coayo72Yj-(KxyE%jA>^E`Nl80#jmRnH*Y{mVD7RFd>MLWLzT% z$n>{>?CL8c>j?<37Be(`*@e{?g%*C#+8g)4Q*&3uP`u0`j#ZA&sxg~6KvDPmRKAYT`iGp*Ox=T{vU&O!F)_ zKk*1KOPkvL?(#XD_;`roV92E_WrW}#-8932n&2y`XO^=L>6MtGf`qtzGRT{FtuDDW z8*h*}(H#7acSL#d(;|>NO0>?6BE2Ow%%tacDSM7v+Z3CyZ$(H$EcC})T{bXe{mrI+ zhIJhWD(<^s#Nx`~obOgibA#CG2VOcRl7Do}+Kbm_Jj}1=7ywl=xPs^?wN{CUi4mab zJT>>LpqUD^i$QR{AZyid<>v=1k>Z&_{*}_BzPQKz3y*VEJJB0bf-fECze%5 zmEf%)9RcsDsDiRX&;f?nZ*3T;n$&ijm~33xAzqiWu?+$tyj^i9+wVVAGHganmTj4& z;thIpF;ewAE49nOj_J3QNIhUuR_3mE@bn%Qn z_*V(4Qj67H@8<6*tgZ5+3HO0*bh0J^iI<59WSBtO7ESL?60h+OuY=FIpCnk*r!~iR*QDfgg&c8zXUXH+P;Ul!cnI6J}pD=rT29 z)VsX&T{fL8Y{RZu*y%TBnSr9(CVX z2%M!;nf2hdsv>AV0&wmkYu?50#o53*3)soZd_3>;%EXJUmI{+6t?O_Mu4amD{v`A} z?dnc%72l5%6J}NHF39C6mtOXhuN!e;$m>| znO9q~1hkAqfPx41ELA)<)mqZ*#y;<-6T;tA0V{2P7T|KagKw_{nZ7Ig!mBAF?at|7 zA9OjPitC-(rLBweT^HWaxuSVso6;G9JHYi_6;4L0&Mf?MPSlz=i*>`yC5unGyszJN zh;4PY(z3O?)CSMNV^xBh(-bP0l+XkKdLiEp literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 000000000..23dfc32b9 --- /dev/null +++ b/index.html @@ -0,0 +1,19 @@ +CC的部落格 - CC康纳百川
2023《好好》线上演唱会
Hexo浏览器定向推送文章更新
语雀文章同步至Hexo笔记
你的公共电视
CC的社畜日记 Part3
CC的社畜日记 Part2
两步验证 最后一道安全防线
Google Adsense 配置手册
如何优雅隐藏 Hexo 文章
第56届电视金钟奖
avatar
CC康纳百川
CC的部落格,CC康纳百川的小窝,与你分享二三事
多种订阅更新方式

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
最近更新
最新评论
正在加载中...
网站资讯
文章数目 :
38
已运行时间 :
本站总字数 :
140.9k
本站访客数 :
本站总访问量 :
最后更新时间 :
\ No newline at end of file diff --git a/js/custom.js b/js/custom.js new file mode 100644 index 000000000..d58a4e7b1 --- /dev/null +++ b/js/custom.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",(()=>{const e=e=>{const t=()=>btf.snackbarShow(GLOBAL_CONFIG.copy.success),n=()=>{if(document.queryCommandSupported&&document.queryCommandSupported("copy")){const n=document.createElement("p");navigator.userAgent.includes("Firefox")?n.textContent=e:n.innerText=e,document.body.appendChild(n);const o=getSelection();o.removeAllRanges();const c=document.createRange();c.selectNodeContents(n),o.addRange(c),document.execCommand("copy"),document.body.removeChild(n),o.removeAllRanges(),t()}else btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport)},o=navigator.clipboard;o?o.writeText(e).then(t).catch(n):n()};document.getElementById("rightside").addEventListener("click",(t=>{const n=t.target.id?t.target:t.target.parentNode;"share-link"===n?.id&&e((()=>{const e=location.protocol+"//"+location.host+location.pathname;return`${document.title}:\r\n${e}`})())}))})); \ No newline at end of file diff --git a/js/main.js b/js/main.js new file mode 100644 index 000000000..e2c5515c6 --- /dev/null +++ b/js/main.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",(function(){let t,e,n=!1;const o=n=>{const o=t=>{let e=0;return t.length&&Array.from(t).forEach((t=>{e+=t.offsetWidth})),e};if(n){const n=o(document.querySelector("#blog-info > a").children),i=o(document.getElementById("menus").children);t=n+i,e=document.getElementById("nav")}let i="";i=window.innerWidth<=768||t>e.offsetWidth-120,i?e.classList.add("hide-menu"):e.classList.remove("hide-menu")},i=()=>{btf.sidebarPaddingR(),document.body.style.overflow="hidden",btf.animateIn(document.getElementById("menu-mask"),"to_show 0.5s"),document.getElementById("sidebar-menus").classList.add("open"),n=!0},c=()=>{const t=document.body;t.style.overflow="",t.style.paddingRight="",btf.animateOut(document.getElementById("menu-mask"),"to_hide 0.5s"),document.getElementById("sidebar-menus").classList.remove("open"),n=!1},s=function(){const t=GLOBAL_CONFIG.highlight;if(!t)return;const{highlightCopy:e,highlightLang:n,highlightHeightLimit:o,plugin:i}=t,c=GLOBAL_CONFIG_SITE.isHighlightShrink,s=e||n||void 0!==c,a="highlighjs"===i?document.querySelectorAll("figure.highlight"):document.querySelectorAll('pre[class*="language-"]');if(!s&&!o||!a.length)return;const l="prismjs"===i,d=!0===c?"closed":"",r=void 0!==c?``:"",u=e?'
':"",m=t=>{const e=t.parentNode;e.classList.add("copy-true");const n=window.getSelection(),o=document.createRange(),i=l?"pre code":"table .code pre";o.selectNodeContents(e.querySelectorAll(`${i}`)[0]),n.removeAllRanges(),n.addRange(o);n.toString();((t,e)=>{if(document.queryCommandSupported&&document.queryCommandSupported("copy"))if(document.execCommand("copy"),void 0!==GLOBAL_CONFIG.Snackbar)btf.snackbarShow(GLOBAL_CONFIG.copy.success);else{const t=e.previousElementSibling;t.textContent=GLOBAL_CONFIG.copy.success,t.style.opacity=1,setTimeout((()=>{t.style.opacity=0}),700)}else void 0!==GLOBAL_CONFIG.Snackbar?btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport):e.previousElementSibling.textContent=GLOBAL_CONFIG.copy.noSupport})(0,t.lastChild),n.removeAllRanges(),e.classList.remove("copy-true")},g=function(t){const e=t.target.classList;e.contains("expand")?(t=>{const e=[...t.parentNode.children].slice(1);t.firstChild.classList.toggle("closed"),btf.isHidden(e[e.length-1])?e.forEach((t=>{t.style.display="block"})):e.forEach((t=>{t.style.display="none"}))})(this):e.contains("copy-button")&&m(this)},h=function(){this.classList.toggle("expand-done")};function f(t,e,n){const i=document.createDocumentFragment();if(s){const e=document.createElement("div");e.className=`highlight-tools ${d}`,e.innerHTML=r+t+u,e.addEventListener("click",g),i.appendChild(e)}if(o&&e.offsetHeight>o+30){const t=document.createElement("div");t.className="code-expand-btn",t.innerHTML='',t.addEventListener("click",h),i.appendChild(t)}"hl"===n?e.insertBefore(i,e.firstChild):e.parentNode.insertBefore(i,e)}l?a.forEach((t=>{if(n){const e=`
${t.getAttribute("data-language")||"Code"}
`;btf.wrap(t,"figure",{class:"highlight"}),f(e,t)}else btf.wrap(t,"figure",{class:"highlight"}),f("",t)})):a.forEach((function(t){if(n){let e=t.getAttribute("class").split(" ")[1];"plain"!==e&&void 0!==e||(e="Code");f(`
${e}
`,t,"hl")}else f("",t,"hl")}))};const a=function(t){const e=t=>{let e="";const n=t=>t.replace(/"/g,""");return t.forEach((t=>{const o=t.alt?`alt="${n(t.alt)}"`:"",i=t.title?`title="${n(t.title)}"`:"";e+=``})),e},n=(t,n,o)=>{const i=o,c=n.length;return c>i?t.insertAdjacentHTML("beforeend",e(n.splice(0,i))):(t.insertAdjacentHTML("beforeend",e(n)),t.classList.remove("lazyload")),c>i?i:c},o=(t,o)=>{if(t.classList.contains("lazyload")){const e=t.getAttribute("data-limit");n(t,o,e);const i=()=>{const c=n(t,o,e);fjGallery(t,"appendImages",t.querySelectorAll(`.fj-gallery-item:nth-last-child(-n+${c})`)),btf.loadLightbox(t.querySelectorAll("img")),c{t.forEach((t=>{t.classList.contains("url")?(async t=>{const e=await fetch(t);return await e.json()})(t.textContent).then((e=>{o(t,e)})):o(t,JSON.parse(t.textContent))}))};window.fjGallery?i():(getCSS(`${GLOBAL_CONFIG.source.justifiedGallery.css}`),getScript(`${GLOBAL_CONFIG.source.justifiedGallery.js}`).then(i))},l=function(){const t=document.getElementById("rightside"),e=window.innerHeight+56;let n=0,o=!0;const i=document.getElementById("page-header"),c="undefined"!=typeof chatBtn,s=GLOBAL_CONFIG.percent.rightside;if(document.body.scrollHeight<=e)return void(t.style.cssText="opacity: 1; transform: translateX(-58px)");const a=btf.throttle((()=>{const a=window.scrollY||document.documentElement.scrollTop,l=(t=>{const e=t>n;return n=t,e})(a);a>56?(l?(i.classList.contains("nav-visible")&&i.classList.remove("nav-visible"),c&&!0===o&&(window.chatBtn.hide(),o=!1)):(i.classList.contains("nav-visible")||i.classList.add("nav-visible"),c&&!1===o&&(window.chatBtn.show(),o=!0)),i.classList.add("nav-fixed"),"0"===window.getComputedStyle(t).getPropertyValue("opacity")&&(t.style.cssText="opacity: 0.8; transform: translateX(-58px)")):(0===a&&i.classList.remove("nav-fixed","nav-visible"),t.style.cssText="opacity: ''; transform: ''"),s&&(t=>{const e=btf.getScrollPercent(t,document.body),n=document.getElementById("go-up");e<95?(n.classList.add("show-percent"),n.querySelector(".scroll-percent").textContent=e):n.classList.remove("show-percent")})(a),document.body.scrollHeight<=e&&(t.style.cssText="opacity: 0.8; transform: translateX(-58px)")}),200);window.scrollCollect=a,window.addEventListener("scroll",scrollCollect)},d=function(){const t=GLOBAL_CONFIG_SITE.isToc,e=GLOBAL_CONFIG.isAnchor,n=document.getElementById("article-container");if(!n||!t&&!e)return;let o,i,c,s,a;if(t){const t=document.getElementById("card-toc");i=t.getElementsByClassName("toc-content")[0],o=i.querySelectorAll(".toc-link"),s=t.querySelector(".toc-percentage"),a=i.classList.contains("is-expand"),window.mobileToc={open:()=>{t.style.cssText="animation: toc-open .3s; opacity: 1; right: 55px"},close:()=>{t.style.animation="toc-close .2s",setTimeout((()=>{t.style.cssText="opacity:''; animation: ''; right: ''"}),100)}},i.addEventListener("click",(t=>{t.preventDefault();const e=t.target.classList;if(e.contains("toc-content"))return;const n=e.contains("toc-link")?t.target:t.target.parentElement;btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI(n.getAttribute("href")).replace("#",""))),300),window.innerWidth<900&&window.mobileToc.close()})),c=t=>{const e=t.getBoundingClientRect().top,n=i.scrollTop;e>document.documentElement.clientHeight-100&&(i.scrollTop=n+150),e<100&&(i.scrollTop=n-150)}}const l=n.querySelectorAll("h1,h2,h3,h4,h5,h6");let d="";window.tocScrollFn=btf.throttle((()=>{const r=window.scrollY||document.documentElement.scrollTop;t&&GLOBAL_CONFIG.percent.toc&&(s.textContent=btf.getScrollPercent(r,n)),function(n){if(0===n)return!1;let s="",r="";if(l.forEach((function(t,e){if(n>btf.getEleTop(t)-80){const n=t.id;s=n?"#"+encodeURI(n):"",r=e}})),d!==r&&(e&&btf.updateAnchor(s),d=r,t)){if(i.querySelectorAll(".active").forEach((t=>{t.classList.remove("active")})),""===s)return;const t=o[r];if(t.classList.add("active"),setTimeout((()=>{c(t)}),0),a)return;let e=t.parentNode;for(;!e.matches(".toc");e=e.parentNode)e.matches("li")&&e.classList.add("active")}}(r)}),100),window.addEventListener("scroll",tocScrollFn)},r=t=>{if(!window.themeChange)return;const e=e=>window.themeChange[e](t);Object.keys(window.themeChange).forEach((t=>{["disqus","disqusjs"].includes(t)?setTimeout((()=>e(t)),300):e(t)}))},u=()=>{const t=document.body;t.classList.add("read-mode");const e=document.createElement("button");e.type="button",e.className="fa-solid fa-sign-out-alt exit-readmode",t.appendChild(e);const n=()=>{t.classList.remove("read-mode"),e.remove(),e.removeEventListener("click",n)};e.addEventListener("click",n)},m=()=>{const t="dark"===document.documentElement.getAttribute("data-theme")?"light":"dark";"dark"===t?(activateDarkMode(),saveToLocal.set("theme","dark",2),void 0!==GLOBAL_CONFIG.Snackbar&&btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)):(activateLightMode(),saveToLocal.set("theme","light",2),void 0!==GLOBAL_CONFIG.Snackbar&&btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)),r(t)},g=t=>{const e=document.getElementById("rightside-config-hide").classList;e.toggle("show"),t.classList.contains("show")&&(e.add("status"),setTimeout((()=>{e.remove("status")}),300)),t.classList.toggle("show")},h=()=>{btf.scrollToDest(0,500)},f=()=>{const t=document.documentElement.classList,e=t.contains("hide-aside")?"show":"hide";saveToLocal.set("aside-status",e,2),t.toggle("hide-aside")},p=()=>{"0"===window.getComputedStyle(document.getElementById("card-toc")).getPropertyValue("opacity")?window.mobileToc.open():window.mobileToc.close()},L=()=>{window.chatBtnFn()};document.getElementById("rightside").addEventListener("click",(function(t){const e=t.target.id?t.target:t.target.parentNode;switch(e.id){case"go-up":h();break;case"rightside_config":g(e);break;case"mobile-toc-button":p();break;case"readmode":u();break;case"darkmode":m();break;case"hide-aside-btn":f();break;case"chat-btn":L()}}));const y=()=>{document.querySelectorAll("#sidebar-menus .site-page.group").forEach((function(t){t.addEventListener("click",(function(){this.classList.toggle("hide")}))}))},b=function(){document.querySelectorAll("#article-container .tab > button").forEach((function(t){t.addEventListener("click",(function(t){const e=this,n=e.parentNode;if(!n.classList.contains("active")){const t=n.parentNode.nextElementSibling,o=btf.siblings(n,".active")[0];o&&o.classList.remove("active"),n.classList.add("active");const i=e.getAttribute("data-href").replace("#","");[...t.children].forEach((t=>{t.id===i?t.classList.add("active"):t.classList.remove("active")}));const c=t.querySelectorAll(`#${i} .fj-gallery`);c.length>0&&btf.initJustifiedGallery(c)}}))}))},v=()=>{document.querySelectorAll("#article-container .tabs .tab-to-top").forEach((function(t){t.addEventListener("click",(function(){btf.scrollToDest(btf.getEleTop(btf.getParents(this,".tabs")),300)}))}))},E=function(t){t.forEach((t=>{const e=t.getAttribute("datetime");t.textContent=btf.diffDate(e,!0),t.style.display="inline"}))};window.refreshFn=function(){o(!0),e.classList.add("show"),GLOBAL_CONFIG_SITE.isPost?(void 0!==GLOBAL_CONFIG.noticeOutdate&&function(){const t=GLOBAL_CONFIG.noticeOutdate,e=btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate);if(e>=t.limitDay){const n=document.createElement("div");n.className="post-outdate-notice",n.textContent=t.messagePrev+" "+e+" "+t.messageNext;const o=document.getElementById("article-container");"top"===t.position?o.insertBefore(n,o.firstChild):o.appendChild(n)}}(),GLOBAL_CONFIG.relativeDate.post&&E(document.querySelectorAll("#post-meta time"))):(GLOBAL_CONFIG.relativeDate.homepage&&E(document.querySelectorAll("#recent-posts time")),GLOBAL_CONFIG.runtime&&(()=>{const t=document.getElementById("runtimeshow");if(t){const e=t.getAttribute("data-publishDate");t.textContent=`${btf.diffDate(e)} ${GLOBAL_CONFIG.runtime}`}})(),(()=>{const t=document.getElementById("last-push-date");if(t){const e=t.getAttribute("data-lastPushDate");t.textContent=btf.diffDate(e,!0)}})(),function(){const t=document.querySelectorAll("#aside-cat-list .card-category-list-item.parent i");t.length&&t.forEach((function(t){t.addEventListener("click",(function(t){t.preventDefault(),this.classList.toggle("expand");const e=this.parentNode.nextElementSibling;btf.isHidden(e)?e.style.display="block":e.style.display="none"}))}))}()),d(),GLOBAL_CONFIG_SITE.isHome&&(()=>{const t=document.getElementById("scroll-down");t&&t.addEventListener("click",(function(){btf.scrollToDest(document.getElementById("content-inner").offsetTop,300)}))})(),s(),GLOBAL_CONFIG.isPhotoFigcaption&&document.querySelectorAll("#article-container img").forEach((function(t){const e=t.parentNode,n=t.title||t.alt;if(n&&!e.parentNode.classList.contains("justified-gallery")){const o=document.createElement("div");o.className="img-alt is-center",o.textContent=n,e.insertBefore(o,t.nextSibling)}})),l();const t=document.querySelectorAll("#article-container .fj-gallery");t.length&&a(t),btf.loadLightbox(document.querySelectorAll("#article-container img:not(.no-lightbox)")),(()=>{const t=document.querySelectorAll("#article-container :not(.highlight) > table, #article-container > table");t.length&&t.forEach((t=>{btf.wrap(t,"div",{class:"table-wrap"})}))})(),function(){const t=document.querySelectorAll("#article-container .hide-button");t.length&&t.forEach((function(t){t.addEventListener("click",(function(t){this.classList.add("open");const e=this.nextElementSibling.querySelectorAll(".fj-gallery");e.length&&btf.initJustifiedGallery(e)}))}))}(),b(),v(),function(){let t=!1;const e=document.querySelector("#comment-switch > .switch-btn");e&&e.addEventListener("click",(function(){this.classList.toggle("move"),document.querySelectorAll("#post-comment > .comment-wrap > div").forEach((function(t){btf.isHidden(t)?t.style.cssText="display: block;animation: tabshow .5s":t.style.cssText="display: none;animation: ''"})),t||"function"!=typeof loadOtherComment||(t=!0,loadOtherComment())}))}(),document.getElementById("toggle-menu").addEventListener("click",(()=>{i()}))},refreshFn(),window.addEventListener("resize",(()=>{o(!1),btf.isHidden(document.getElementById("toggle-menu"))&&n&&c()})),document.getElementById("menu-mask").addEventListener("click",(t=>{c()})),y(),GLOBAL_CONFIG.islazyload&&(window.lazyLoadInstance=new LazyLoad({elements_selector:"img",threshold:0,data_src:"lazy-src"})),void 0!==GLOBAL_CONFIG.copyright&&(()=>{const t=GLOBAL_CONFIG.copyright;document.body.oncopy=e=>{e.preventDefault();const n=window.getSelection(0).toString();let o=n;return n.length>t.limitCount&&(o=`${n}\n\n\n${t.languages.author}\n${t.languages.link}${window.location.href}\n${t.languages.source}\n${t.languages.info}`),e.clipboardData?e.clipboardData.setData("text",o):window.clipboardData.setData("text",o)}})(),GLOBAL_CONFIG.autoDarkmode&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(t=>{void 0===saveToLocal.get("theme")&&(t.matches?r("dark"):r("light"))}))})); \ No newline at end of file diff --git a/js/search/algolia.js b/js/search/algolia.js new file mode 100644 index 000000000..b88fa0623 --- /dev/null +++ b/js/search/algolia.js @@ -0,0 +1 @@ +window.addEventListener("load",(()=>{const e=document.getElementById("search-mask"),t=document.querySelector("#algolia-search .search-dialog"),a=()=>{const a=document.body.style;a.width="100%",a.overflow="hidden",btf.animateIn(e,"to_show 0.5s"),btf.animateIn(t,"titleScale 0.5s"),setTimeout((()=>{document.querySelector("#algolia-search .ais-SearchBox-input").focus()}),100),document.addEventListener("keydown",(function e(t){"Escape"===t.code&&(i(),document.removeEventListener("keydown",e))})),n(),window.addEventListener("resize",n)},i=()=>{const a=document.body.style;a.width="",a.overflow="",btf.animateOut(t,"search_close .5s"),btf.animateOut(e,"to_hide 0.5s"),window.removeEventListener("resize",n)},n=()=>{window.innerWidth<768&&t.style.setProperty("--search-height",window.innerHeight+"px")},s=()=>{document.querySelector("#search-button > .search").addEventListener("click",a)},o=GLOBAL_CONFIG.algolia;if(!(o.appId&&o.apiKey&&o.indexName))return console.error("Algolia setting is invalid!");const r=instantsearch({indexName:o.indexName,searchClient:algoliasearch(o.appId,o.apiKey),searchFunction(e){e.state.query&&e.search()}}),l=instantsearch.widgets.configure({hitsPerPage:o.per_page||5}),d=instantsearch.widgets.searchBox({container:"#algolia-search-input",showReset:!1,showSubmit:!1,searchAsYouType:!1,showLoadingIndicator:!0,autofocus:!0,placeholder:GLOBAL_CONFIG.algolia.languages.input_placeholder}),c=instantsearch.widgets.hits({container:"#algolia-hits",templates:{item(e){const t=e.permalink?e.permalink:GLOBAL_CONFIG.root+e.path,a=e._snippetResult.contentStrip.value;return`\n ")-3,a.indexOf(""))}-,${a.substring(a.indexOf("")+6,a.indexOf(""))},-${a.substring(a.indexOf("")+7,a.indexOf("")+10)}" class="algolia-hit-item-link">\n ${e._highlightResult.title.value||"no-title"}\n
${a}
\n 匹配字词: ${e._highlightResult.contentStrip.matchedWords} | 匹配等级: ${e._highlightResult.contentStrip.matchLevel}\n
`},empty:function(e){return'
'+GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/,e.query)+"
"}}}),h=instantsearch.widgets.stats({container:"#algolia-info > .algolia-stats",templates:{text:function(e){return`
${GLOBAL_CONFIG.algolia.languages.hits_stats.replace(/\$\{hits}/,e.nbHits).replace(/\$\{time}/,e.processingTimeMS)}`}}}),g=instantsearch.widgets.poweredBy({container:"#algolia-info > .algolia-poweredBy"}),u=instantsearch.widgets.pagination({container:"#algolia-pagination",totalPages:o.totalPages,templates:{first:'',last:'',previous:'',next:''}});r.addWidgets([l,d,c,h,g,u]),r.start(),s(),e.addEventListener("click",i),document.querySelector("#algolia-search .search-close-button").addEventListener("click",i),window.addEventListener("pjax:complete",(()=>{!btf.isHidden(e)&&i(),s()})),window.pjax&&r.on("render",(()=>{window.pjax.refresh(document.getElementById("algolia-hits"))}))})); \ No newline at end of file diff --git a/js/search/local-search.js b/js/search/local-search.js new file mode 100644 index 000000000..7c6ecc50f --- /dev/null +++ b/js/search/local-search.js @@ -0,0 +1 @@ +class LocalSearch{constructor({path:e="",unescape:t=!1,top_n_per_article:n=1}){this.path=e,this.unescape=t,this.top_n_per_article=n,this.isfetched=!1,this.datas=null}getIndexByWord(e,t,n=!1){const s=[],o=new Set;return n||(t=t.toLowerCase()),e.forEach((e=>{if(this.unescape){const t=document.createElement("div");t.innerText=e,e=t.innerHTML}const i=e.length;if(0===i)return;let r=0,a=-1;for(n||(e=e.toLowerCase());(a=t.indexOf(e,r))>-1;)s.push({position:a,word:e}),o.add(e),r=a+i})),s.sort(((e,t)=>e.position!==t.position?e.position-t.position:t.word.length-e.word.length)),[s,o]}mergeIntoSlice(e,t,n){let s=n[0],{position:o,word:i}=s;const r=[],a=new Set;for(;o+i.length<=t&&0!==n.length;){a.add(i),r.push({position:o,length:i.length});const e=o+i.length;for(n.shift();0!==n.length&&(s=n[0],o=s.position,i=s.word,e>o);)n.shift()}return{hits:r,start:e,end:t,count:a.size}}highlightKeyword(e,t){let n="",s=t.start;for(const{position:o,length:i}of t.hits)n+=e.substring(s,o),s=o+i,n+=`${e.substr(o,i)}`;return n+=e.substring(s,t.end),n}getResultItems(e){const t=[];return this.datas.forEach((({title:n,content:s,url:o})=>{const[i,r]=this.getIndexByWord(e,n),[a,c]=this.getIndexByWord(e,s),l=new Set([...r,...c]).size,h=i.length+a.length;if(0===h)return;const d=[];0!==i.length&&d.push(this.mergeIntoSlice(0,n.length,i));let u=[];for(;0!==a.length;){const e=a[0],{position:t}=e,n=Math.max(0,t-20),o=Math.min(s.length,t+100);u.push(this.mergeIntoSlice(n,o,a))}u.sort(((e,t)=>e.count!==t.count?t.count-e.count:e.hits.length!==t.hits.length?t.hits.length-e.hits.length:e.start-t.start));const g=parseInt(this.top_n_per_article,10);g>=0&&(u=u.slice(0,g));let p="";(o=new URL(o,location.origin)).searchParams.append("highlight",e.join(" ")),0!==d.length?p+=`
${this.highlightKeyword(n,d[0])}`:p+=`",t.push({item:p,id:t.length,hitCount:h,includedCount:l})})),t}fetchData(){const e=!this.path.endsWith("json");fetch(this.path).then((e=>e.text())).then((t=>{this.isfetched=!0,this.datas=e?[...(new DOMParser).parseFromString(t,"text/xml").querySelectorAll("entry")].map((e=>({title:e.querySelector("title").textContent,content:e.querySelector("content").textContent,url:e.querySelector("url").textContent}))):JSON.parse(t),this.datas=this.datas.filter((e=>e.title)).map((e=>(e.title=e.title.trim(),e.content=e.content?e.content.trim().replace(/<[^>]+>/g,""):"",e.url=decodeURIComponent(e.url).replace(/\/{2,}/g,"/"),e))),window.dispatchEvent(new Event("search:loaded"))}))}highlightText(e,t,n){const s=e.nodeValue;let o=t.start;const i=[];for(const{position:e,length:r}of t.hits){const t=document.createTextNode(s.substring(o,e));o=e+r;const a=document.createElement("mark");a.className=n,a.appendChild(document.createTextNode(s.substr(e,r))),i.push(t,a)}e.nodeValue=s.substring(o,t.end),i.forEach((t=>{e.parentNode.insertBefore(t,e)}))}highlightSearchWords(e){const t=new URL(location.href).searchParams.get("highlight"),n=t?t.split(" "):[];if(!n.length||!e)return;const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null),o=[];for(;s.nextNode();)s.currentNode.parentNode.matches("button, select, textarea, .mermaid")||o.push(s.currentNode);o.forEach((e=>{const[t]=this.getIndexByWord(n,e.nodeValue);if(!t.length)return;const s=this.mergeIntoSlice(0,e.nodeValue.length,t);this.highlightText(e,s,"search-keyword")}))}}window.addEventListener("load",(()=>{const{path:e,top_n_per_article:t,unescape:n,languages:s}=GLOBAL_CONFIG.localSearch,o=new LocalSearch({path:e,top_n_per_article:t,unescape:n}),i=document.querySelector("#local-search-input input"),r=document.getElementById("local-search-stats-wrap"),a=document.getElementById("loading-status"),c=()=>{if(!o.isfetched)return;const e=i.value.trim().toLowerCase();""!==e&&(a.innerHTML='');const t=e.split(/[-\s]+/),n=document.getElementById("local-search-results");let c=[];if(e.length>0&&(c=o.getResultItems(t)),1===t.length&&""===t[0])n.classList.add("no-result"),n.textContent="";else if(0===c.length)n.textContent="",r.innerHTML=`
${s.hits_empty.replace(/\$\{query}/,e)}
`;else{c.sort(((e,t)=>e.includedCount!==t.includedCount?t.includedCount-e.includedCount:e.hitCount!==t.hitCount?t.hitCount-e.hitCount:t.id-e.id));const e=s.hits_stats.replace(/\$\{hits}/,c.length);n.classList.remove("no-result"),n.innerHTML=`
${c.map((e=>e.item)).join("")}
`,r.innerHTML=`
${e}
`,window.pjax&&window.pjax.refresh(n)}a.textContent=""};let l=!1;const h=document.getElementById("search-mask"),d=document.querySelector("#local-search .search-dialog"),u=()=>{window.innerWidth<768&&d.style.setProperty("--search-height",window.innerHeight+"px")},g=()=>{const e=document.body.style;e.width="100%",e.overflow="hidden",btf.animateIn(h,"to_show 0.5s"),btf.animateIn(d,"titleScale 0.5s"),setTimeout((()=>{i.focus()}),300),l||(!o.isfetched&&o.fetchData(),i.addEventListener("input",c),l=!0),document.addEventListener("keydown",(function e(t){"Escape"===t.code&&(p(),document.removeEventListener("keydown",e))})),u(),window.addEventListener("resize",u)},p=()=>{const e=document.body.style;e.width="",e.overflow="",btf.animateOut(d,"search_close .5s"),btf.animateOut(h,"to_hide 0.5s"),window.removeEventListener("resize",u)},m=()=>{document.querySelector("#search-button > .search").addEventListener("click",g)};window.addEventListener("search:loaded",(()=>{const e=document.getElementById("loading-database");e.nextElementSibling.style.display="block",e.remove()})),m(),document.querySelector("#local-search .search-close-button").addEventListener("click",p),h.addEventListener("click",p),GLOBAL_CONFIG.localSearch.preload&&o.fetchData(),o.highlightSearchWords(document.getElementById("article-container")),window.addEventListener("pjax:complete",(()=>{!btf.isHidden(h)&&p(),o.highlightSearchWords(document.getElementById("article-container")),m()}))})); \ No newline at end of file diff --git a/js/tw_cn.js b/js/tw_cn.js new file mode 100644 index 000000000..8c7050f62 --- /dev/null +++ b/js/tw_cn.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",(function(){const{defaultEncoding:t,translateDelay:e,msgToTraditionalChinese:n,msgToSimplifiedChinese:a}=GLOBAL_CONFIG.translate,o=GLOBAL_CONFIG.Snackbar;let l=t;const c="translate-chn-cht";let d,i=void 0===saveToLocal.get(c)?t:Number(saveToLocal.get("translate-chn-cht"));const r=void 0!==o;function h(){document.documentElement.lang=1===i?"zh-TW":"zh-CN"}function s(t){return""===t||null==t?"":1===l&&2===i?function(t){let e="";const n="万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释里鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾龙历志制一台皋准复猛钟注范签",a="萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備複夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋裏钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽龍歷誌製壹臺臯準復勐鐘註範籤";for(let o=0;o1e4&&-1!==a.indexOf(t.charAt(o))?e+=n.charAt(a.indexOf(t.charAt(o))):e+=t.charAt(o);return e}(t):2===l&&1===i?function(t){let e="";const n="万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释里鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾龙历志制一台皋准复猛钟注范签",a="萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備複夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋裏钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽龍歷誌製壹臺臯準復勐鐘註範籤";for(let o=0;o1e4&&-1!==n.indexOf(t.charAt(o))?e+=a.charAt(n.indexOf(t.charAt(o))):e+=t.charAt(o);return e}(t):t}function u(t){let e;e="object"==typeof t?t.childNodes:document.body.childNodes;for(let t=0;t0||n===d||(""!==n.title&&null!=n.title&&(n.title=s(n.title)),""!==n.alt&&null!=n.alt&&(n.alt=s(n.alt)),""!==n.placeholder&&null!=n.placeholder&&(n.placeholder=s(n.placeholder)),"INPUT"===n.tagName&&""!==n.value&&"text"!==n.type&&"hidden"!==n.type&&(n.value=s(n.value)),3===n.nodeType?n.data=s(n.data):u(n))}}function f(){1===i?(l=1,i=2,d.textContent=n,r&&btf.snackbarShow(o.cht_to_chs)):2===i&&(l=2,i=1,d.textContent=a,r&&btf.snackbarShow(o.chs_to_cht)),saveToLocal.set(c,i,2),h(),u()}function m(){d=document.getElementById("translateLink"),d&&(l!==i&&(d.textContent=1===i?a:n,h(),setTimeout(u,e)),d.addEventListener("click",f,!1))}m(),document.addEventListener("pjax:complete",m)})); \ No newline at end of file diff --git a/js/utils.js b/js/utils.js new file mode 100644 index 000000000..1a4b6f524 --- /dev/null +++ b/js/utils.js @@ -0,0 +1 @@ +const btf={debounce:function(t,e,n){let o;return function(){const i=this,a=arguments,r=n&&!o;clearTimeout(o),o=setTimeout((function(){o=null,n||t.apply(i,a)}),e),r&&t.apply(i,a)}},throttle:function(t,e,n){let o,i,a,r=0;n||(n={});const s=function(){r=!1===n.leading?0:(new Date).getTime(),o=null,t.apply(i,a),o||(i=a=null)};return function(){const l=(new Date).getTime();r||!1!==n.leading||(r=l);const c=e-(l-r);i=this,a=arguments,c<=0||c>e?(o&&(clearTimeout(o),o=null),r=l,t.apply(i,a),o||(i=a=null)):o||!1===n.trailing||(o=setTimeout(s,c))}},sidebarPaddingR:()=>{const t=window.innerWidth,e=document.body.clientWidth,n=t-e;t!==e&&(document.body.style.paddingRight=n+"px")},snackbarShow:(t,e=!1,n=2e3)=>{const{position:o,bgLight:i,bgDark:a}=GLOBAL_CONFIG.Snackbar,r="light"===document.documentElement.getAttribute("data-theme")?i:a;Snackbar.show({text:t,backgroundColor:r,showAction:e,duration:n,pos:o,customClass:"snackbar-css"})},diffDate:(t,e=!1)=>{const n=new Date,o=new Date(t),i=n.getTime()-o.getTime(),a=36e5,r=24*a,{dateSuffix:s}=GLOBAL_CONFIG;if(!e)return parseInt(i/r);const l=i/2592e6,c=i/r,d=i/a,u=i/6e4;return l>12?o.toISOString().slice(0,10):l>=1?`${parseInt(l)} ${s.month}`:c>=1?`${parseInt(c)} ${s.day}`:d>=1?`${parseInt(d)} ${s.hour}`:u>=1?`${parseInt(u)} ${s.min}`:s.just},loadComment:(t,e)=>{if("IntersectionObserver"in window){const n=new IntersectionObserver((t=>{t[0].isIntersecting&&(e(),n.disconnect())}),{threshold:[0]});n.observe(t)}else e()},scrollToDest:(t,e=500)=>{const n=window.pageYOffset,o=document.getElementById("page-header").classList.contains("fixed");if((n>t||o)&&(t-=70),"scrollBehavior"in document.documentElement.style)return void window.scrollTo({top:t,behavior:"smooth"});let i=null;t=+t,window.requestAnimationFrame((function o(a){i=i||a;const r=a-i;n{t.style.display="block",t.style.animation=e},animateOut:(t,e)=>{t.addEventListener("animationend",(function e(){t.style.display="",t.style.animation="",t.removeEventListener("animationend",e)})),t.style.animation=e},getParents:(t,e)=>{for(;t&&t!==document;t=t.parentNode)if(t.matches(e))return t;return null},siblings:(t,e)=>[...t.parentNode.children].filter((n=>e?n!==t&&n.matches(e):n!==t)),wrap:(t,e,n)=>{const o=document.createElement(e);for(const[t,e]of Object.entries(n))o.setAttribute(t,e);t.parentNode.insertBefore(o,t),o.appendChild(t)},unwrap:t=>{const e=t.parentNode;e&&e!==document.body&&e.replaceChild(t,e)},isHidden:t=>0===t.offsetHeight&&0===t.offsetWidth,getEleTop:t=>{let e=t.offsetTop,n=t.offsetParent;for(;null!==n;)e+=n.offsetTop,n=n.offsetParent;return e},loadLightbox:t=>{const e=GLOBAL_CONFIG.lightbox;"mediumZoom"===e&&mediumZoom(t,{background:"var(--zoom-bg)"}),"fancybox"===e&&(t.forEach((t=>{if("A"!==t.parentNode.tagName){const e=t.dataset.lazySrc||t.src,n=t.title||t.alt||"";btf.wrap(t,"a",{href:e,"data-fancybox":"gallery","data-caption":n,"data-thumb":e})}})),window.fancyboxRun||(Fancybox.bind("[data-fancybox]",{Hash:!1,Thumbs:{showOnStart:!1},Images:{Panzoom:{maxScale:4}},Carousel:{transition:"slide"},Toolbar:{display:{left:["infobar"],middle:["zoomIn","zoomOut","toggle1to1","rotateCCW","rotateCW","flipX","flipY"],right:["slideshow","thumbs","close"]}}}),window.fancyboxRun=!0))},initJustifiedGallery:function(t){const e=t=>{btf.isHidden(t)||fjGallery(t,{itemSelector:".fj-gallery-item",rowHeight:t.getAttribute("data-rowHeight"),gutter:4,onJustify:function(){this.$container.style.opacity="1"}})};0===Array.from(t).length?e(t):t.forEach((t=>{e(t)}))},updateAnchor:t=>{if(t!==window.location.hash){t||(t=location.pathname);const e=GLOBAL_CONFIG_SITE.title;window.history.replaceState({url:location.href,title:e},e,t)}},getScrollPercent:(t,e)=>{const n=e.clientHeight,o=document.documentElement.clientHeight,i=(t-e.offsetTop)/(n>o?n-o:document.documentElement.scrollHeight-o),a=Math.round(100*i);return a>100?100:a<=0?0:a},addModeChange:(t,e)=>{window.themeChange&&window.themeChange[t]||(window.themeChange={...window.themeChange,[t]:e})}}; \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 000000000..f70c64dd7 --- /dev/null +++ b/manifest.json @@ -0,0 +1 @@ +{"name":"CC的部落格","short_name":"CC","description":"CC的部落格,CC康纳百川的小窝,与你分享二三事","theme_color":"#8fbc8f","background_color":"#ffcc33","display":"minimal-ui","scope":"/","start_url":".","icons":[{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/36.png","sizes":"36x36","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/48.png","sizes":"48x48","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/72.png","sizes":"72x72","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/96.png","sizes":"96x96","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/144.png","sizes":"144x144","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/apple-touch-icon.png","sizes":"180x180","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/192.png","sizes":"192x192","type":"image/png"},{"src":"https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/image/pwa/512.png","sizes":"512x512","type":"image/png"}]} \ No newline at end of file diff --git a/moments/index.html b/moments/index.html new file mode 100644 index 000000000..5e1a57da8 --- /dev/null +++ b/moments/index.html @@ -0,0 +1,19 @@ +CC的友链朋友圈 | CC的部落格

CC的友链朋友圈


评论
\ No newline at end of file diff --git a/music/index.html b/music/index.html new file mode 100644 index 000000000..5497f7f9d --- /dev/null +++ b/music/index.html @@ -0,0 +1,19 @@ +音乐 | CC的部落格

音乐

Three Man Down × Tilly Birds

2022年8月22日 Ohm宣布因个人原因退出乐队,"TMD"因此也成为了缺少贝斯手的乐队

王铮亮

王铮亮2023“还是爱着”全国巡演(网易云音乐)

王铮亮2023“还是爱着”全国巡演(QQ音乐)

\ No newline at end of file diff --git a/newPost.json b/newPost.json new file mode 100644 index 000000000..d38c37ec2 --- /dev/null +++ b/newPost.json @@ -0,0 +1 @@ +{"title":"你以为 AddThis 只是个分享工具吗?","updated":"2023-06-25T20:44:00+08:00","message":"本文介绍了 AddThis 的使用","target_url":"https://blog.ccknbc.cc/posts/the-real-addthis/","image":"https://pic1.afdiancdn.com/user/8a7f563c2e3811ecab5852540025c377/common/bbf0970587cfd0f4a654efda9c375844_w1920_h1080_s216.jpg","categories":["工具"],"schedule":"2023-07-11T15:41:25.803Z","expire":"7d","auto_hide":"1"} \ No newline at end of file diff --git a/offline/index.html b/offline/index.html new file mode 100644 index 000000000..22ea8d643 --- /dev/null +++ b/offline/index.html @@ -0,0 +1,19 @@ +CC的部落格 离线页面 | CC的部落格

CC的部落格 离线页面

很抱歉,您暂时无法访问CC的部落格,因此跳转到离线页面

这有可能是CC的主站服务器全部炸裂,当然,也可能的是您网络丢失,或者至少您与CC的服务器之间失去了联系。

可前往 CC的状态页面 查看故障详情或反馈,也可手动暂时访问下列镜像站点,感谢您的支持与理解!

以下排名不分先后,请选择适合自己访问较快的即可
GitHub | GitLab | Gitee | Bitbucket | Vercel | Netlify | CloudFlare | Zeabur

\ No newline at end of file diff --git a/page/2/index.html b/page/2/index.html new file mode 100644 index 000000000..f04703679 --- /dev/null +++ b/page/2/index.html @@ -0,0 +1,19 @@ +CC的部落格 - CC康纳百川
CC的社畜日记 Part1
Ta 什么都不说
你以为 AddThis 只是个分享工具吗?
Cusdis 还是 Disqus ?
Hexo Butterfly Algolia 搜索的使用
很棒的状态页面
Hexo标签笔记
GitHub 自动合并 PR 笔记
Waline 评论系统部署日志
一款简洁却不简单的 m3u8 下载工具
avatar
CC康纳百川
CC的部落格,CC康纳百川的小窝,与你分享二三事
多种订阅更新方式

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
最近更新
最新评论
正在加载中...
网站资讯
文章数目 :
38
已运行时间 :
本站总字数 :
140.9k
本站访客数 :
本站总访问量 :
最后更新时间 :
\ No newline at end of file diff --git a/page/3/index.html b/page/3/index.html new file mode 100644 index 000000000..0d91d6ca9 --- /dev/null +++ b/page/3/index.html @@ -0,0 +1,19 @@ +CC的部落格 - CC康纳百川
基于小波变换的图像去噪技术研究
提问的智慧
语雀专用测试文章
博客图片的 WebP 之路
我真的不想要 .html
各大音乐平台歌单转换
课程设计
为你的 Hexo 博客添加邮件订阅
如何在中国大陆享受 JOOX 音乐服务
Github Actions 为什么这么香
avatar
CC康纳百川
CC的部落格,CC康纳百川的小窝,与你分享二三事
多种订阅更新方式

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
最近更新
最新评论
正在加载中...
网站资讯
文章数目 :
38
已运行时间 :
本站总字数 :
140.9k
本站访客数 :
本站总访问量 :
最后更新时间 :
\ No newline at end of file diff --git a/page/4/index.html b/page/4/index.html new file mode 100644 index 000000000..26f392a97 --- /dev/null +++ b/page/4/index.html @@ -0,0 +1,19 @@ +CC的部落格 - CC康纳百川
我为什么选择了 Tidio 做聊天系统
简历模板
第55届金钟奖相关
Uptime 免费网站存活监控
简单浏览器更新推送的实现
HEXO 折腾
生产实习
基于小波变换的数字水印检测
avatar
CC康纳百川
CC的部落格,CC康纳百川的小窝,与你分享二三事
多种订阅更新方式

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
最近更新
最新评论
正在加载中...
网站资讯
文章数目 :
38
已运行时间 :
本站总字数 :
140.9k
本站访客数 :
本站总访问量 :
最后更新时间 :
\ No newline at end of file diff --git a/posts/2fa-last-security-line/index.html b/posts/2fa-last-security-line/index.html new file mode 100644 index 000000000..25f363828 --- /dev/null +++ b/posts/2fa-last-security-line/index.html @@ -0,0 +1,19 @@ +两步验证 最后一道安全防线 | CC的部落格

两步验证 最后一道安全防线

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

查看本文语雀版本【首发】,自动同步更新至CC 的部落格

起因

写这篇文章的起因很简单,就是那天早上醒来看到一条短信(很巧,9 号正是谷歌为所有用户启用两步验证的日子) 然后赶紧打开邮箱查看通知,并登录修改密码 虽然是我不怎么使用的老帐号,但是还是觉得有点恐怖,对于像我这样很多平台都使用一个密码的人来说,如果没有两步验证,我可能要失去账号使用权了,毕竟还是有很多回忆,因此如何友好的使用 2FA 是个问题,而我也在慢慢学习。

探索

说到帐号安全,大家都知道国内很多网络服务 (如淘宝、银行),除了正确的帐号密码之外,常常还需要额外给你发一条手机短信验证码,以此进一步确认你是帐号的真正主人。这其实就是「两步验证」或者叫做「双因素验证」的一种实现方式,它这里第二步验证是靠手机短信来发送验证码的。而国外更多的网站/网络服务还会使用一种叫“身份验证器”或叫“虚拟 MFA”的二步验证方式,它是利用一种“随时间变化的验证码”来取代手机短信,不仅更安全,而且可离线使用,通用性也更强……

开启两步验证/双重验证有什么好处?

和短信验证码一样道理,这里的两步验证也是相当于给帐号多加一把“锁”(多一步的验证),在输入正确的账号密码之后,用户同样还需要额外输入一个每 30 秒自动变化一次的 6 位数字「二步验证码」才能完成登录。

所以即使你的帐号和密码不慎泄露了,别人在没有这个数字验证码也是无法登录你的账号的,这可以大大提高破解的难度和帐号的安全性。所以建议所有能开启二步验证的重要网络帐号都要全部开启。

二步验证和手机短信验证码有什么区别?

手机短信验证码和两步验证的目的和作用基本一致,不过很多的 (国外) 网络服务并不支持发送手机短信验证码,主要是短信成本高,而且有安全性风险 (比如 2G 网络下黑客可以利用 GSM 漏洞监听截取到用户的手机号码和短信内容)。

而本文所说的二步验证是指虚拟 MFA,或者说是“身份验证器”,是基于时间和加密算法生成“每 30 秒变化一次的 6 位数字验证码”,也叫做 TOTP (Time-Based One-time Password) 或 OTP 一次性密码。它的优点是使用时无需联网、仅需时间进行计算、速度快、可离线使用、没有额外成本、算法协议公开通用,开发和使用上都很简单,可以用小型硬件 (实体的密码器) 或纯软件 APP 来实现,因此更多的网站会支持这种方式。

两步验证、MFA、2FA、多因素验证都是些什么鬼?

我们常常会见到“两步验证”、“二步验证”、“双因素验证”、“多因素验证”、“虚拟 MFA”、“动态令牌”、“双重验证”、“2FA”、“Two-Factor Authentication”、“Multi-Factor Authentication”、“OTP”、“TOTP”等等词语,不过你完全不需要被吓到。

因为其实它们都是在说同一个意思,就是除帐号密码这一个因素以外,再多增加一个要验证的因素。实现形式可以是用手机短信、邮件来发送验证码,也可以是本文所述的基于时间生成“不断变化”的一次性数字验证码。

怎样使用二步验证?身份验证器/密码器 APP 推荐

那么,既然不靠手机短信发送验证码?我要从哪里得到这个不断变化的 6 位数字二步验证码呢?其实我们只需要安装一个「二步验证 APP」(身份验证器应用) 来生成它即可。这类密码器 APP 有很多,后面会介绍。

值得了解的是,大多数网站的帮助和提示上都以 Google Authenticator (谷歌身份验证器) 这款 APP 作为例子,但其实,这类二步验证应用 / 身份验证器 APP 都是遵循 TOTP 协议 (同一套加密算法) 生成验证码的,所以它们完全通用,使用上也大同小异,用户只需按喜好选择即可,而不是必须选择某一个 APP 的。

Authy - 最好用的二步验证 / 身份验证器 APP

Authy 是我个人最推荐的二步验证密码生成器 APP 应用,它完全免费,全平台通用,支持 iOS / Android / Windows / macOS/Linux 系统,提供 Chrome 的浏览器插件(已经停止服务),而且可以备份数据,并支持跨设备同步,可以一 APP 通行全部支持 TOTP 两步验证的网站。

1Password

1Password 可以说是最出色的跨平台密码管理器,唯一的缺点就是稍贵。它除了支持帐号密码管理以及自动填写密码等功能以外,新版本同样「也可以支持一次性密码 (TOTP 两步验证码)」,数据可以云端同步,使用上非常方便,据说就连苹果也为员工统一配备此 APP。

Microsoft Authenticator - 微软身份验证器

顾名思义,这个就是由微软开发的两步验证器应用,完全免费,跨平台支持 iOS 和安卓,界面简约。新版本增加了数据备份功能,因此也是一个不错的选择。

不推荐使用 Google 身份验证器

相对的,我个人**「并不建议」使用 Google 身份验证器**,尽管很多网站推会荐它,我认为这只是因为它免费、Google 的影响力大、并且它出现得比较早而且。它的缺点非常明显——不支持数据备份!(非常鸡肋的二维码换机备份功能)

也就是说,如果手机丢失或刷机清空数据后,你的网络账号就麻烦了 (因为你必须使用原来设置两步验证时留存的备用码进行恢复)。而 Authy 或 1Password 这些可以备份和同步的 APP 则没有这个担忧。

如果你是用的是安卓手机,或许可以试试Aegis这款应用,它的备份导入导出功能也是不错的,方便一键换机,也支持中文,而且开源免费!

怎样开启两步验证?

一般在支持二步验证的网站上 (比如我知道的就有:阿里云、腾讯云、Amazon、Humble Bundle、坚果云、Dropbox、Linode、GitHub、微软帐号、Google 帐号、Twitter、Instagram、NameSilo、印象笔记等等),在其“帐号”或“安全”相关页面就能找到「开启两步验证」的选项,然后它就会给你出示一个二维码让你扫描,这时候,你使用任何两步验证的密码认证器 APP (身份验证器应用) ,比如上面推荐的 Authy 扫描一下这个二维码进行即可完成“配对 / 绑定”。之后你就能在 APP 里面获取登录所需的 6 位数字一次性验证码了!此外网站通常会提供一串代码供手动复制粘贴添加,一般来说复制粘贴均可自动识别。 这时你还需要回到网站上,输入正确的验证码,然后点确认保存一下,成功之后该帐号即会正式启用 TOTP 方式的两步验证。值得注意的是,在“绑定”成功并启用二步验证后,部分网站会给你提供一些「备用代码」(备用安全码 / 恢复码) 作为应急手段,在你丢失二步验证设备或数据的情况下,可以用它们来登录并取消二步验证,它们相当于是解除二步验证的最后一条钥匙。所以务必要保存好这些备用安全码,个人建议可以将它们保存在印象笔记、1Password 或者打印出来存放好。否则当意外情况发生 (无法获得二步验证码) 后,你又没有这个恢复码时,你的账号可能将永远无法被访问。所以,备用码非常重要!非常重要!非常重要!切记要备份好! 不同的网站/网络服务开通使用密码认证器的两步验证的流程基本都一样,只是网站界面显示有所不同,大家可以逐一登录到各个网站后台账户页面去看看具体怎样设置。

分享

其实网上关于这个话题已经有很多优秀帖子,博文,所以这篇文章不会过多讲什么,当一个记录罢了。

总之,重要的网络账号单单只靠密码来保证安全是不够稳妥的,因为它们很容易泄露。「两步验证」才是目前互联网上最佳的安全举措,你不应该忽略它。

对于重要的账号,基本上只要开启了两步验证并且保存好备用恢复码,它们就几乎不可能被陌生人盗用,轻松把帐号被盗的损失风险和概率降到了最低。所以,如果你之前没试过,那么看完这篇文章后,建议你把支持两步验证的网站都开启它。

从哪里下载虚拟验证器

Authy 官网:https://authy.com Microsoft Authenticator 官网:https://www.microsoft.com/zh-cn/account/authenticator Google Authenticator 官网:https://www.google.cn/intl/zh-CN/landing/2step/index.html Aegis 主页:https://getaegis.app/

可能会用到的资料

Authy 和 Google Authenticator 对比:https://authy.com/blog/authy-vs-google-authenticator Microsoft Authenticator 使用方法:http://www.xitongtiandi.net/wenzhang/win10/26184.html 支持二次验证的网络服务:https://www.appinn.com/10-two-factor-authentication

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/2fa-last-security-line/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/56th-golden-bell-awards/index.html b/posts/56th-golden-bell-awards/index.html new file mode 100644 index 000000000..4af6f54ad --- /dev/null +++ b/posts/56th-golden-bell-awards/index.html @@ -0,0 +1,19 @@ +第56届电视金钟奖 | CC的部落格

第56届电视金钟奖

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

本文首发在语雀 自动同步更新至CC 的部落格

第 56 届电视金钟奖 56th Golden Bell Awards
日期2021 年 10 月 2 日
地点台北市国父纪念馆
国家或地区台湾
主办单位指导单位:台湾文化部、主办单位:文化部影视及流行音乐产业局、承办单位:三立电视
主持人陈子见
预展主持人黄豪平蔡尚桦(星光大道)
官方网站gba.tavis.tw
电视/电台转播
电视网络电视:三立都会台 三立戏剧台(MOD) 公共电视全球直播:三立国际台 新加坡 STARHUB 马来西亚 Unifi TV 东森美洲电视网络:广播电视金钟奖 YouTube 频道 Vidol LINE TODAY 三立新闻网 中华电信 Hami Video Yahoo TV 广播:人人电台(好事 989 电台
时长4 小时 43 分钟

| ← 第 55 届金钟奖第 57 届 → | |

第 56 届电视金钟奖(英语:56th Golden Bell Awards / 56th GBA)是 2021 年台湾传媒的年度盛事之一,以表扬 2021 年度杰出的台湾电视从业人员,此届开放在中国台湾合法设立或登记之网络影音平台可报名参赛(目前仅限“综艺节目”、“益智及实境节目”,但公开传输必须达 8 集、上述影音平台不包括FacebookYouTube)。[1]颁奖典礼于2021年10月2日在台北市国父纪念馆举行,典礼主持人陈子见,星光大道主持人黄豪平蔡尚桦

目录

播放平台

电视金钟奖

电视现场直播

频道所在地区播出日期播出时间
三立都会台台湾2021 年 10 月 2 日17:00-19:00(星光大道) 19:00-23:43(颁奖典礼)

| 公视主频(仅转播颁奖典礼) | | | | | 公视 3 台(仅转播星光大道) | | | | | 三立戏剧台中华电信 MOD ) | | | | | 三立国际台 | 全球 | | | | StarHub | 新加坡 | | | | Unifi TV | 马来西亚 | | |

网络平台直播

频道所在地区播出日期播出时间
三立新闻网台湾2021 年 10 月 2 日17:00-19:00(星光大道) 19:00-23:43(颁奖典礼)
Vidol

| 中华电信 HAMI VIDEO | | | | | LINE TODAY | | | | | 金钟 56 官网 | 全球 | | | | 金钟YouTube 频道 | | | | | 金钟 56 APP | | | |

电台直播

频道所在地区播出日期播出时间
好事 989 电台台湾2021 年 10 月 2 日19:00-22:42(颁奖典礼,仅转播表演节目)

电视类入围暨得奖名单

节目奖

戏剧节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司曹瑞原
我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之传播有限公司
客家寻味剧场-《女孩上场客家电视台、魔幻时刻电影有限公司
黑喵知情酷斯本媒体制作股份有限公司
飘洋过海来爱你盛达影像制作有限公司、财团法人慈济传播人文志业基金会

迷你剧集奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
大债时代财团法人公共电视文化事业基金会、用力拍电影有限公司锺欣凌黄镫辉
戒指流浪记晴天影像股份有限公司
返校财团法人公共电视文化事业基金会、边境映象艺文有限公司
获奖做工的人大慕影艺国际事业股份有限公司、凯擘影艺股份有限公司、台湾大哥大股份有限公司华研国际音乐股份有限公司、家庭票房股份有限公司(HBO ASIA)
预支未来百薇国际娱乐股份有限公司、满满额娱乐股份有限公司

电视电影奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
公视人生剧展 ─《人生清理员果陀娱乐传播有限公司王净李沐
获奖《主管再见》影一制作所股份有限公司
客家电影院 ─《光的孩子》客家电视台、境外即思有限公司
客家电影院 ─《窝卡》客家电视台
《蟾鸣》财团法人公共电视文化事业基金会、夏日静好影像有限公司

自然科学纪实节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《台湾的前世今生》壹传媒电视广播股份有限公司锺瑶
《地球的孤儿:台湾的精灵》东森电视事业股份有限公司
获奖《福尔摩沙守謢者》东森电视事业股份有限公司
《台湾,风起!》东台传播股份有限公司

人文纪实节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖《不羁 ─ 台湾百年流变与停泊》十月影视有限公司锺瑶
《巷弄里的吉光片羽》客家电视台
《活力新故乡》客家电视台、八方汇盈数位制作股份有限公司
《群山之岛与不去会死的他们》叁喜映画股份有限公司、财团法人公共电视文化事业基金会
艺术很有事财团法人公共电视文化事业基金会

儿童少年节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖《kakudan 时光机》财团法人原住民族文化事业基金会彭小刀孙协志许孟哲
《Try 科学》财团法人慈济传播人文志业基金会
《我家住海边》奇妙创造股份有限公司、财团法人公共电视文化事业基金会
《神厨赛恩师》财团法人公共电视文化事业基金会
《酷 WAWA》财团法人原住民族文化事业基金会

生活风格节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
大云时堂台湾优视媒体科技股份有限公司沈玉琳Melody
《台湾好滋味》中华电视股份有限公司、天马传播事业有限公司
《我又在市场待了一整天》财团法人公共电视文化事业基金会
《无事坐巴士》财团法人公共电视文化事业基金会-公视台语台
获奖谁来晚餐 12财团法人公共电视文化事业基金会

综艺节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
36 题爱上你财团法人公共电视文化事业基金会曾国城浩子
《Semenay 我们的歌》财团法人原住民族文化事业基金会
《一个都不能少》八大电视股份有限公司友松娱乐股份有限公司
《画说 Lulu》斯尔夫股份有限公司、台湾大哥大股份有限公司
获奖菱格世代 DD52野火娱乐制作有限公司、联联看娱乐文化股份有限公司

益智及实境节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《今天谁来店》巧克科技新媒体股份有限公司沈春华
《公视主题之夜 SHOW》财团法人公共电视文化事业基金会
全民星攻略东森电视事业股份有限公司友松娱乐股份有限公司
获奖全明星运动会台湾电视事业股份有限公司三立电视股份有限公司好看娱乐制作股份有限公司
阮三个 餐车环岛发大财 2财团法人公共电视文化事业基金会、用力拍电影有限公司

动画节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《布农神话》青铜视觉艺术有限公司彭小刀孙协志许孟哲
获奖《未来宅急便》财团法人公共电视文化事业基金会、兔子创意股份有限公司
吉娃斯爱科学:新同学来了》财团法人公共电视文化事业基金会、原金国际有限公司
我的泰山爸爸乐群动画制作股份有限公司

个人奖

戏剧节目男主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李奕樵天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司郑元畅
施名帅黑喵知情酷斯本媒体制作股份有限公司
唐治平我家的美好时光财团法人慈济传播人文志业基金会、金品国际多媒体有限公司
许杰辉我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之传播有限公司
获奖薛仕凌生生世世台湾电视事业股份有限公司、松大娱乐经纪股份有限公司

戏剧节目女主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李维维罗雀高飞三立电视股份有限公司、黄杨文化工作室姚淳耀柯佳嬿
孙可芳若是一个人中华电视股份有限公司、宝丽国际娱乐股份有限公司
孙淑媚天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限司、台湾大哥大股份有限公司
蔡嘉茵客家寻味剧场-《女孩上场客家电视台、魔幻时刻电影有限公司
获奖锺欣凌我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司

戏剧节目男配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖Darren【邱凯伟】我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司锺欣凌黄镫辉
朱轩洋天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司
林鹤轩若是一个人中华电视股份有限公司、宝丽国际娱乐股份有限公司
梁正群黑喵知情酷斯本媒体制作股份有限公司
杨铭威我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司

戏剧节目女配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
黄舒湄天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司锺欣凌黄镫辉
黄姵嘉我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司
刘品言未来妈妈三立电视股份有限公司台湾大哥大股份有限公司、怡佳娱乐经纪股份有限公司、好看娱乐制作股份有限公司
卢以恩天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司
获奖简嫚书她们创业的那些鸟事可米传媒事业股份有限公司、八大电视股份有限公司

戏剧节目最具潜力新人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖李奕樵天桥上的魔术师
财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司王净李沐
阮秋姮飘洋过海来爱你
盛达影像制作有限公司、财团法人慈济传播人文志业基金会
林洁宜天桥上的魔术师
财团法人公共电视文化事业基金会
、原子映象有限公司、台湾大哥大股份有限公司
高倩怡客家寻味剧场 ─《女孩上场客家电视台
、魔幻时刻电影有限公司
罗谦绍天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司

迷你剧集/电视电影男主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
安原良客家电影院 ─《光的孩子》客家电视台、境外即思有限公司游安顺薛仕凌
获奖李铭顺做工的人大慕影艺国际事业股份有限公司
李历融《主管再见》影一制作所股份有限公司
唐川客家电影院 ─《窝卡》客家电视台
刘冠廷致亲爱的孤独者 ─ 小薰一条龙虎豹国际娱乐有限公司、梦田影像股份有限公司

迷你剧集/电视电影女主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李雪致亲爱的孤独者 ─ 凯涵梦田影像股份有限公司游安顺薛仕凌
林予晞戒指流浪记晴天影像股份有限公司
苗可丽做工的人大慕影艺国际事业股份有限公司
获奖徐堰铃客家电影院 ─《光的孩子》客家电视台、境外即思有限公司
陆弈静《阿嬷的放屁车》界面影像有限公司

迷你剧集/电视电影男配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
张复建【张建陵】公视人生剧展 ─《面容》希力创意国际股份有限公司于子育吴以涵
陈恩《主管再见》影一制作所股份有限公司
游安顺做工的人大慕影艺国际事业股份有限公司
戴立忍公视新创电影:《访客》奇妙创造股份有限公司、财团法人公共电视文化事业基金会
获奖薛仕凌做工的人大慕影艺国际事业股份有限公司

迷你剧集/电视电影女配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
Janet【谢怡芬】戒指流浪记晴天影像股份有限公司于子育吴以涵
获奖小薰【黄瀞怡】大债时代财团法人公共电视文化事业基金会、用力拍电影有限公司
方宥心做工的人大慕影艺国际事业股份有限公司
陈又瑄公视迷你电影院—《家庭式》财团法人公共电视文化事业基金会、青东有限公司
潘丽丽大债时代财团法人公共电视文化事业基金会、用力拍电影有限公司

迷你剧集/电视电影最具潜力新人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
王岚申公视学生剧展—《爬出棺财板》奇诺影像有限公司于子育吴以涵
夏胧预支未来百薇国际娱乐股份有限公司、满满额娱乐股份有限公司
郭美华公视迷你电影院—《家庭式》财团法人公共电视文化事业基金会、青东有限公司
获奖游珈瑄公视迷你电影院—《家庭式》财团法人公共电视文化事业基金会、青东有限公司
黄冠智返校边境映象艺文有限公司、财团法人公共电视文化事业基金会

戏剧节目导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
吴宗叡客家寻味剧场 ─《女孩上场魔幻时刻电影有限公司曹瑞原
杜政哲若是一个人中华电视股份有限公司、宝丽国际娱乐股份有限公司
陈保中、包祥麟黑喵知情酷斯本媒体制作股份有限公司
获奖杨雅喆天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司
邓安宁我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司

迷你剧集/电视电影导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
林亚佑《主管再见》影一制作所股份有限公司锺欣凌黄镫辉
徐丽雯客家电影院 ─《光的孩子》客家电视台、境外即思有限公司
陈大璞公视人生剧展 ─《人生清理员果陀娱乐传播有限公司
获奖郑芬芬做工的人大慕影艺国际事业股份有限公司
温晴客家电影院 ─《窝卡》客家电视台

戏剧节目编剧奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖张逸宁、吴岱芸、吴宗叡、陈南宏客家寻味剧场 ─《女孩上场魔幻时刻电影有限公司郑元畅
杨雅喆、蒋友竹、陈虹任、吴季恩天桥上的魔术师财团法人公共电视文化事业基金会
、原子映象有限公司、台湾大哥大股份有限公司
温怡惠、林珮瑜、黄元蓓、谢梦迁、邓安宁陈慧玲王文娟我的婆婆怎么那么可爱财团法人公共电视文化事业基金会、群之噰传播有限公司
刘中薇未来妈妈三立电视股份有限公司台湾大哥大股份有限公司、怡佳娱乐经纪股份有限公司、好看娱乐制作股份有限公司
谢宗臣、柯尊仁黑喵知情酷斯本媒体制作股份有限公司

迷你剧集/电视电影编剧奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖徐丽雯客家电影院 ─《光的孩子》客家电视台
、境外即思有限公司孙淑媚曾敬骅
马自明、张可欣、陈定宁、安邦廖士涵大债时代财团法人公共电视文化事业基金会、用力拍电影有限公司
高妙慧、范芷绮、文采戒指流浪记晴天影像股份有限公司
郑仰山、康语妮公视人生剧展 ─《人生清理员果陀娱乐传播有限公司
郑芬芬、洪兹盈做工的人大慕影艺国际事业股份有限公司

自然科学及人文纪实节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
白心仪《地球的孤儿:台湾的精灵》东森电视事业股份有限公司锺瑶
米沙【温尹嫦】《老派美学的约会》影相人视觉开发有限公司
获奖舒梦兰《福尔摩沙守謢者》东森电视事业股份有限公司
杨小黎在台湾的故事三立电视股份有限公司
罗亦娌《巷弄里的吉光片羽》客家电视台

儿童少年节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖Lan-pao【薛纪纲】《Kakudan 时光机》财团法人原住民族文化事业基金会彭小刀孙协志许孟哲
王伯源陈玮薇《Try 科学》财团法人慈济传播人文志业基金会
亚里【廖敏君】《台湾囝仔赞》财团法人公共电视文化事业基金会
纳豆【林郁智】、史达鲁【沈祐谦】、邱凡书、赖冠宇《神厨赛恩师》财团法人公共电视文化事业基金会
锺欣凌郭彦均超级总动员东森电视事业股份有限公司

生活风格节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖大霈【李霈瑜】原来是匠紫三立电视股份有限公司沈玉琳Melody
李四端大云时堂台湾优视媒体科技股份有限公司
李明璁《我又在市场待了一整天》财团法人公共电视文化事业基金会
高怡平《家庭八点档转转发现爱》米迦勒传播事业股份有限公司
窦智孔【窦允辰】《台湾第一等》八大电视股份有限公司

综艺节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
胡瓜【胡自雄】阿翔【陈秉立】综艺大集合民间全民电视股份有限公司
、大艺娱乐企业有限公司曾国城浩子
获奖唐绮阳吴姗儒炎亚纶【吴庚霖】36 题爱上你财团法人公共电视文化事业基金会
马世芳【马芳】音乐万万岁第 4 号作品财团法人公共电视文化事业基金会
黄子佼一个都不能少八大电视股份有限公司友松娱乐股份有限公司
澎恰恰【彭高尚】话山话水话玲珑财团法人公共电视文化事业基金会、全能制作公司

益智及实境节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
吴宗宪KID【林柏昇】小鬼【黄鸿升】综艺玩很大三立电视股份有限公司好看娱乐制作股份有限公司沈春华
徐乃麟曾国城
张文绮【张镫匀】徐凯希【徐亦晴】天才冲冲冲中华电视股份有限公司、金是传媒行销企业有限公司
获奖曾国城一字千金财团法人公共电视文化事业基金会
曾宝仪我们回家吧斯尔夫股份有限公司 台湾大哥大股份有限公司

技术类奖项

非戏剧类节目导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖李立劭公视纪实 ─《独舞者的乐章》艾巴克影像体有限公司锺瑶
李鹤寿、林雨禅《我又在市场待了一整天》─ 岛民的自信海味:澎湖北宸市场财团法人公共电视文化事业基金会
林琬玉文化容颜 ─《建筑 秋华 王秋华》财团法人公共电视文化事业基金会
符昌锋、王俊雄《不羁 ─ 台湾百年流变与停泊》十月影视有限公司
卢晓筠公视纪实 ─《月港蜂云》哈鲁影像有限公司

非戏剧类节目导播奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
可乐【吴佩谕】菱格世代 DD52野火娱乐制作有限公司、联联看娱乐文化股份有限公司吴姗儒炎亚纶
获奖李丽芳第 16 届 KKBOX 风云榜颁奖典礼台湾电视事业股份有限公司
周天麟、陈宛婷、林雅萍公视主题之夜 SHOW财团法人公共电视文化事业基金会
陈美而《BMW M 20/21 aMEI UTOPIA EAST 阿妹 台东跨年》联利媒体股份有限公司
黄慧娟公视表演厅 击乐剧场《泥巴》财团法人公共电视文化事业基金会

戏剧类节目摄影奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
古曜华、刘韦昇黑喵知情酷斯本媒体制作股份有限公司温贞菱
林众甫公视新创电影:《访客奇妙创造股份有限公司、财团法人公共电视文化事业基金会
获奖陈克勤、高子皓天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司
蔡旻翰公视人生剧展 ─《人生清理员果陀娱乐传播有限公司
简佑陶爱的广义相对论 ─《最后一战》文达文创股份有限公司、香港商福斯传媒有限公司

非戏剧类节目摄影奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
林俊岚、Jose Miguel Garcia Sanchez、胡德炜客家文艺复兴第二季:《靓靓六堆》美商国家地理频道有限公司-台湾分公司沈玉琳Melody
高誉展 、巫少强上山下海过一夜三立电视股份有限公司
获奖陈一松、陈相宇、陈昱翔《福尔摩沙守謢者》东森电视事业股份有限公司
陈韦翰、王艾如、程纪皓《群山之岛与不去会死的他们》叁喜映画股份有限公司、财团法人公共电视文化事业基金会
麦觉明、余瑞祥MIT 台湾志大麦影像传播工作室

戏剧类节目剪辑奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
江翊宁返校边境映象艺文有限公司、财团法人公共电视文化事业基金会温贞菱
李俊宏做工的人大慕影艺国际事业股份有限公司
林劭慈公视迷你电影院—《家庭式》财团法人公共电视文化事业基金会、青东有限公司
获奖姜叙佩公视人生剧展 ─《人生清理员果陀娱乐传播有限公司
高鸣晟、王瀞巧《主管再见》影一制作所股份有限公司

非戏剧类节目剪辑奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李立劭公视纪实 ─《独舞者的乐章》艾巴克影像体有限公司沈玉琳Melody
李鹤寿《我又在市场待了一整天》─ 岛民的自信海味:澎湖北宸市场财团法人公共电视文化事业基金会
获奖洪瑞忆、许聪仁《不羁 ─ 台湾百年流变与停泊》十月影视有限公司
许雅婷公视纪实—《斜坡上的老歌手》好丰盛电影有限公司
谢欣志公视纪实—《为寂寞在唱歌》大逆光影音制作有限公司

声音设计奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
王榆钧、林传智、叶之圣公视新创电影:《访客奇妙创造股份有限公司、财团法人公共电视文化事业基金会孙淑媚曾敬骅
周泓历、施钧耀、高伟晏《蟾鸣》夏日静好影像有限公司
林冠戎、张哲纲、梁忠颖、陈居正、李轩霆公视学生剧展—《爬出棺财板》奇诺影像有限公司
获奖林耿农《不羁 ─ 台湾百年流变与停泊》十月影视有限公司
杨凯婷、沈志朋公视人生剧展 ─《人生清理员果陀娱乐传播有限公司

灯光奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李培源预支未来百薇国际娱乐股份有限公司、满满额娱乐股份有限公司温贞菱
陈冠廷爱的广义相对论 ─ 最后一战》文达文创股份有限公司、香港商福斯传媒有限公司
获奖叶明广天桥上的魔术师财团法人公共电视文化事业基金会、原子映象有限公司、台湾大哥大股份有限公司
谢松铭《主管再见》影一制作所股份有限公司
锺琼婷返校境映象艺文有限公司、财团法人公共电视文化事业基金会

美术设计奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
王登钰、余聿、王景贤《布农神话》青铜视觉艺术有限公司孙淑媚曾敬骅
获奖王志成、王佳惠、叶智雄、杨喻宪、郭家宥天桥上的魔术师财团法人公共电视文化事业基金会
、原子映象有限公司、台湾大哥大股份有限公司
郭语彤公视迷你电影院―《家庭式》财团法人公共电视文化事业基金会、青东有限公司
陈韦中公视人生剧展―《人生清理员果陀娱乐传播有限公司
郑予舜公视新创电影:《访客奇妙创造股份有限公司、财团法人公共电视文化事业基金会

节目创新奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《不羁 ─ 台湾百年流变与停泊》十月影视有限公司吴姗儒炎亚纶
《今天谁来店》巧克科技新媒体股份有限公司
获奖全明星运动会台湾电视事业股份有限公司三立电视股份有限公司好看娱乐制作股份有限公司
菱格世代 DD52野火娱乐制作有限公司、联联看娱乐文化股份有限公司
群山之岛与不去会死的他们叁喜映画股份有限公司、财团法人公共电视文化事业基金会

特别奖

特殊贡献奖

得奖者引言人/颁奖嘉宾
获奖任立渝詹怡宜

多项入围

入围数量获奖数量节目名称入围奖项名字结果参考
146天桥上的魔术师戏剧节目奖天桥上的魔术师获奖
戏剧节目男主角奖李奕樵提名[2]
戏剧节目女主角奖孙淑媚提名
戏剧节目男配角奖朱轩洋提名
戏剧节目女配角奖黄舒湄提名
卢以恩提名
戏剧节目最具潜力新人奖李奕樵获奖
林洁宜提名
罗谦绍提名
戏剧节目导演奖杨雅喆获奖
戏剧节目编剧奖杨雅喆、蒋友竹、陈虹任、吴季恩提名
戏剧类节目摄影奖陈克勤、高子皓获奖
灯光奖叶明广获奖
美术设计奖王志成、王佳惠、叶智雄、杨喻宪、郭家宥获奖
94做工的人迷你剧集奖做工的人获奖
迷你剧集(电视电影)男主角奖李铭顺获奖
迷你剧集(电视电影)女主角奖苗可丽提名
迷你剧集(电视电影)男配角奖游安顺提名
薛仕凌获奖
迷你剧集(电视电影)女配角奖方宥心提名
迷你剧集(电视电影)导演奖郑芬芬获奖
迷你剧集(电视电影)编剧奖郑芬芬、洪兹盈提名
戏剧类节目剪辑奖李俊宏提名
82我的婆婆怎么那么可爱戏剧节目奖我的婆婆怎么那么可爱提名
戏剧节目男主角奖许杰辉提名
戏剧节目女主角奖锺欣凌获奖
迷你剧集(电视电影)男配角奖Darren【邱凯伟】获奖
杨铭威提名
戏剧节目女配角奖黄姵嘉提名
戏剧节目导演奖邓安宁提名
戏剧节目编剧奖温怡惠、林珮瑜、黄元蓓、谢梦迁 邓安宁陈慧玲王文娟提名

追思逝世电视人

特别演唱者:魏如萱以下是追思电视人的名单:

  • 长青 —— 演员、主持人
  • 管管 —— 演员、诗人
  • 李玉芬 —— 演员、配音员
  • 郑少峰 —— 导演
  • 钱璐 —— 演员
  • 黄民安 —— 演员
  • 王吉宣 —— 乐队总指挥
  • 糖糖 —— 演员
  • 查马克·法拉屋乐 —— 演员
  • 简持中 —— 编剧
  • 张家铭 —— 灯光师
  • 洪麟 —— 演员
  • 龙劭华 —— 演员

表演节目

表演嘉宾演出主题演出内容
陈明章按下 PAUSE 键之后陈明章〈下午的一出戏〉 黄妃
〈追追追〉 陈明章〈伊是咱的宝贝〉
陈子见吴姗儒炎亚纶这是综艺新视代脱口秀
动力火车向世界说我们的故事孙盛希

〈小心翻阅〉《天桥上的魔术师》片尾曲 方宥心〈牵你的手〉《飘洋过海来爱你》片尾曲 傅薇〈甜甜甜〉《我的婆婆怎么那么可爱》片尾曲 周兴哲〈如果能幸福〉《戒指流浪记》片尾曲 周予天〈小小的爱〉《黑喵知情》片头曲 麋先生〈废废〉《大债时代》片尾曲 陈娴静许琼文〈你和我想的不一样〉《女孩上场》片尾曲 陈娴静何欣穗〈相反〉《返校》片尾曲 9m88 〈看不见的城〉《预支未来》片尾曲 动力火车〈永远不再〉《做工的人》片尾曲 |

评审名单

电视金钟奖评审名单

主任委员
曹瑞原
特别奖主任委员
林福地
戏剧节目
李远曹瑞原李志蔷陈慧翎、傅天余、曾瀚贤、温昇豪温郁芳、杨智麟、杨谨华、郑心媚
迷你剧集/电视电影
刘梓洁尹馨王传宗邱泽陈和榆冯勃棣黄姵嘉、詹京霖、萧力修
自然科学纪实节目/人文纪实节目
萧菊贞、吴奕蓉、李香秀、蔡崇隆、郑国威
儿童少年节目
冷彬、王耿瑜、朱曙明、陈芝安、赵亦瑄 (米可白)
生活风格节目
舞赛、姚淳耀、古拉斯、水瓶子、李俊明刘永伟
综艺节目/益智及实境节目
赖勋彪、白汝珊、周咏训侯怡君侯昌明廖科溢、谢政豪
动画节目
林家齐、纪柏舟、叶仁豪
技术奖
刘嵩、王希文、周震、姚执善、陈胜昌、黄文英、蔡珮玲、郑志良、郑慧玲、袁绪虎、宋文忠 、陈柏佑、韩纪轩、苏耑宥
特别奖评审委员
林福地、汤昇荣、蔡振南陈亚兰许杰辉、廖筱君、李天怡
文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/56th-golden-bell-awards/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
目录
  1. 1. 目录
  2. 2. 播放平台
    1. 2.1. 电视金钟奖
      1. 2.1.1. 电视现场直播
      2. 2.1.2. 网络平台直播
      3. 2.1.3. 电台直播
  3. 3. 电视类入围暨得奖名单
    1. 3.1. 节目奖
      1. 3.1.1. 戏剧节目奖
      2. 3.1.2. 迷你剧集奖
      3. 3.1.3. 电视电影奖
      4. 3.1.4. 自然科学纪实节目奖
      5. 3.1.5. 人文纪实节目奖
      6. 3.1.6. 儿童少年节目奖
      7. 3.1.7. 生活风格节目奖
      8. 3.1.8. 综艺节目奖
      9. 3.1.9. 益智及实境节目奖
      10. 3.1.10. 动画节目奖
    2. 3.2. 个人奖
      1. 3.2.1. 戏剧节目男主角奖
      2. 3.2.2. 戏剧节目女主角奖
      3. 3.2.3. 戏剧节目男配角奖
      4. 3.2.4. 戏剧节目女配角奖
      5. 3.2.5. 戏剧节目最具潜力新人奖
      6. 3.2.6. 迷你剧集/电视电影男主角奖
      7. 3.2.7. 迷你剧集/电视电影女主角奖
      8. 3.2.8. 迷你剧集/电视电影男配角奖
      9. 3.2.9. 迷你剧集/电视电影女配角奖
      10. 3.2.10. 迷你剧集/电视电影最具潜力新人奖
      11. 3.2.11. 戏剧节目导演奖
      12. 3.2.12. 迷你剧集/电视电影导演奖
      13. 3.2.13. 戏剧节目编剧奖
      14. 3.2.14. 迷你剧集/电视电影编剧奖
      15. 3.2.15. 自然科学及人文纪实节目主持人奖
      16. 3.2.16. 儿童少年节目主持人奖
      17. 3.2.17. 生活风格节目主持人奖
      18. 3.2.18. 综艺节目主持人奖
      19. 3.2.19. 益智及实境节目主持人奖
    3. 3.3. 技术类奖项
      1. 3.3.1. 非戏剧类节目导演奖
      2. 3.3.2. 非戏剧类节目导播奖
      3. 3.3.3. 戏剧类节目摄影奖
      4. 3.3.4. 非戏剧类节目摄影奖
      5. 3.3.5. 戏剧类节目剪辑奖
      6. 3.3.6. 非戏剧类节目剪辑奖
      7. 3.3.7. 声音设计奖
      8. 3.3.8. 灯光奖
      9. 3.3.9. 美术设计奖
    4. 3.4. 节目创新奖
    5. 3.5. 特别奖
      1. 3.5.1. 特殊贡献奖
    6. 3.6. 多项入围
    7. 3.7. 追思逝世电视人
  4. 4. 表演节目
  5. 5. 评审名单
    1. 5.1. 电视金钟奖评审名单

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
\ No newline at end of file diff --git a/posts/a-simple-but-not-simple-m3u8-download-tool/index.html b/posts/a-simple-but-not-simple-m3u8-download-tool/index.html new file mode 100644 index 000000000..b0473f989 --- /dev/null +++ b/posts/a-simple-but-not-simple-m3u8-download-tool/index.html @@ -0,0 +1,19 @@ +一款简洁却不简单的 m3u8 下载工具 | CC的部落格

一款简洁却不简单的 m3u8 下载工具

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

本文首发在语雀 自动同步更新至CC 的部落格 官方仓库

批量下载优酷 m3u8 LINETV(台湾站解析) 其实 SimpleG 提供了 CLI 更直观简单的调用方式,因此更加方便快捷,解密,录直播必备。

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
avatar
CC康纳百川
CC的部落格,CC康纳百川的小窝,与你分享二三事
多种订阅更新方式

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
最近更新
\ No newline at end of file diff --git a/posts/about-pts/index.html b/posts/about-pts/index.html new file mode 100644 index 000000000..12b54191c --- /dev/null +++ b/posts/about-pts/index.html @@ -0,0 +1,19 @@ +你的公共电视 | CC的部落格

你的公共电视

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

查看本文语雀版本【首发】,自动同步更新至CC 的部落格

作为一个大陆人,时常希望有一个独立于官媒的非自媒体存在,你可能会提到傲娇的“六公主”;而这次,我想和大家聊一聊这个台湾媒体中特别的存在【公共电视】

关于公视

公视使命

“公共电视”是一种电视制度, 在传播学理上有其定义与任务。

它必须有自己的频道、 自己的电台、 有自己的节目政策, 所有的播出都是为了服务公众, 提供公众必须的资讯为主要功能。

因此, 公视和宣导政令的国家电视不同, 和以广告、收视率好坏来取决节目内容的商业电视不同。

公视属于全体民众, 不专为政府或某一政党服务; 不以营利为目的, 也不受商业或利益团体左右, 公共电视,顾名思义, 是接收全民付託, 以服务公共利益为宗旨的电视媒体。

那【公视】与 【台视】【华视】【民视】【中视】等带有明显倾向色彩的电视台有什么不同呢?台湾虽然本土面积不大,但却拥有者 300 多家电视台,在这里开电视台,真的就是靠财团砸钱。你或许知道【中视】与【中天】的老板是同一个,没错就是“旺旺”,因此你可以经常看到记者手持两家电视台的麦克风,一条新闻两台播,这样比较省钱啦,而因为具有明显的亲中色彩,两家在岛内的收视率或许并没有那么高,【中天新闻台】也只是被迫改为网络播出。

台湾公广集团有:公共电视,PTS Taiwan (English),公视台语台,中华电视公司,客家电视台

那你也就可以理解为什么【公视】经常称呼【华视】为友台,一开始我们有提到过,它并不在乎自己的收视率,因此不论你何时切到公视,都是没有广告的,这与其他频道是一个明显的区别;那上面提到过运营一家电视台真的很烧钱,公视为什么每年还有那么多自制剧,资金链从哪来?

经费来源

世界上其他国家也有公共媒体,不同于 NHK, BBC,公民需要每年像这些公共媒体强制性缴纳费用,公视经费主要来源有以下

  1. 公视基金会第一年得到的政府捐赠 为十二亿元新台币, 自筹款为三亿元。依据公共电视法, 政府捐赠的金额逐年递减百分之十, 至第六年以后应为第一年政府编列预算 金额的百分之五十, 因此公视自筹款负担将逐年大幅增加, 对一个肩负使命的非营利电视台而言, 无疑是一个高难度的挑战。为避免过于倚赖政府捐赠, 以增加公视财务独立性,在作法上有:

  2. 企业赞助:由公、私立机构或企业团体提供经费,赞助播出之时段或节目。“企业赞助”不同于一般广告赞助,受限于电视台的基本规范,不得促销特定商品或服务、不与节目题材有任何关联或暗示、不参与任何节目制播过程等,因此能够独立自主, 避免伴随经费而来的干预。公视节目品质精緻、立意良善, 受到许多公、私立机构、企业予以肯定,并提供经费赞助, 成为公视制作精緻节目的重要支柱。

  3. 个人捐赠:成立“公视之友”会员制度,希望汇集来自民间的力量,成为公共电视在民间的重要基础。“公视之友”认同本会理念 并以捐款的方式赞助公视,公视除制作精良的节目外, 以《公视之友》月刊做为与“公视之友”沟通的桥樑,此外亦提供“公视之友”适当的回馈,如购买本会相关产品享有折扣优惠、不定期举办专题讲座等。同时, 举办文化、教育、残障等公益活动时,邀请“公视之友”担任志工, 让公共电视提倡的理念落实到生活中。

  4. 其它财源:公视拥有各类型精緻的节目为基础,利于开发各项公共电视文化事业活动,如促销与节目相关之录影带、 图书资料、教材及副产品等, 将节目资源再利用,延伸节目的制作价值。此外, 公视摄影棚、剪辑、音效等设备,在法规允许的范围内,行有馀力时, 予以出租,供其它传播公司、大学相关科系 付费使用,以合理的租金做为硬体维护费用。公视开播以来, 积极争取企业赞助,并以节目行销、 设备出租的方式获取经费; 公共电视更透过一步一脚印的 地方巡迴服务、 各项媒体的宣传及社会大众的推荐,使“公视之友”人数迅速成长,这正代表公视的理念与品质受到肯定, 成为公视往前迈进的最大动力。

算下来,台湾人每年向公视提供 35 新台币的支持,因此每位台湾人都是公视的“干爸/干妈”

中国台湾公共電視台
英國公共電視台
美國公共電視台
日本 NHK 公共電視台
法國公共電視台 Francetv.fr
法國公共電視台 ARTE
法國公共電視台 法國法蘭西 24
加拿大公共電視台
澳洲公共電視台
德國公共電視台
澳洲公共電視台(SBS)
丹麥公共電視台
西班牙公共電視台
挪威公共電視台
瑞典公共電視台
芬蘭公共電視台

创办历史

公视建台历史

1980年

当时的行政院长孙运璿先生提出公共电视台的主张。他说,今天不做,明天会后悔。

1983年

新闻局提出公视节目制作中心计划草案,但因经费过高、人力庞大而搁置。

1984年

新闻局设立公共电视制播小组,向三家无线电视台徵用时段播出。

1986年

公共电视节目制作的任务,转由财团法人广电基金下设的公共电视节目制播组负责, 广电基金所制作的节目,仍然没有专属频道播出,在三台借用的时段经常被调动,影响观众收视权益。

1991年

行政院核定公共电视台筹备委员会设置点,公视筹委会正式运作。公视筹委会委託七位学者专家组成公共电视法草案立法小组,并经过缜密的研议,提出公共电视法草案。

1993年

行政院将公共电视法送交立法院审查。

1996年9月

一群关心公共电视的学术文化界人士 ,组成公共媒体催生联盟,结合各界支持公共电视的力量, 以促使公视法通过。

1997年5月31日

经由民间锲而不捨的游说及 立法院密集的政党协商, 公视法惊险过关,完成三读。

1998年1月

第一届公共电视董监事十八位人选经立法院推举的提名审查委员会审议通过。三月,董监事召开第一次会议,选出吴丰山先生为董事长, 贺德芬女士为常务监事。

1998年7月1日

财团法人公共电视文化事业基金会 正式成立,公共电视台并于同日开播,完成长达十八年的建台历程。

公视的未来有很长的路要走, 许多困难与险阻有待我们一一克服,而您正站在公视成长的时间轴上,见证改造省内媒体环境的长期奋战, 公视盼与您携手,共同为打造媒体的美丽新“视”界努力!

公视已在 2018 年走过了 20 个年头,而“看见更好的未来”是时代赋予它的新使命,此外公视还是全台第一家试验 4K 播出的电视台

制播理念

以多元的视野、多样的风貌和 高品质的专业制作来服务公众, 促进教育文化发展, 是全世界公共电视节目共同的特色, 也是公视奋力追求的目标。在节目规划上,公视秉持以下九大理念:

  1. 真心关爱儿童的成长
  2. 尊重各族群的需求
  3. 关怀弱势团体与文化
  4. 呈现表演艺术的生命力
  5. 重视台湾生态保育
  6. 纪录台湾社会变迁及人文风貌
  7. 亲近民众的生活
  8. 展现文学之美
  9. 掌握社会脉动、开拓国际视野

公视节目不以单一节目吸引大量观众, 而是透过整体节目表的安排,由多元样貌的节目来满足不同族群, 或不同爱好者的特殊需求。为了向民众提供 有别于商业逻辑的更佳选择, 公视的节目制作涵盖下列目标:提供全民终身学习的管道。增进人民对新闻事件和公共事务的瞭解,善尽媒体监督政府的第四权责任。提供重要议题和观念的分析和解释。提供人民对台湾和他国丰富文化、 历史的认知, 并培养本土关怀和国际视野。增进国际社会对台湾风土人情的瞭解。使人民接触多元的表演艺术。提供各种社会团体如少数民族、弱势团体,公平参与的机会与表达艺术和政治上的意见空间。播映和典藏重要的影视经典作品。

因为有《公共电视法》的庇护,公视在这些年里是有制播许多优秀节目的,这里不再一一列出,光是看“广播电视金钟奖”入围获奖名单都可以知道。

公开透明

这是公共媒体一个显著的特征,因为这个媒体是属于人民,服务人民的,并受到人们监督。所有相关信息,均可在官网查询到,不过仍然要遵循 CC 创用规则哦。

频道

公视主频是台湾的公共电视媒体——公共电视台(公视)的主频道,一般称呼为“公共电视”或简称为“公视”(部分节目预告片尾将本频道称呼为“公视频道”)。内容为综合台形式,特色是比其他无线台(台视、中视、华视、民视)更重视公共服务节目及弱势族群(儿童、老人、原住民族等)节目。中央气象局发布海上台风警报期间,公视主频道会在每整点前数分钟固定录影转播中央气象局台风动态说明会,也会在画面左侧开启滚动字幕报导台风最新动态及台风警报范围。公视的台标在节目播完后会由半透明变成“彩色”。 2012 年 6 月 30 日中午起,无线电视数字化后定频于 26 频道。 2016 年 6 月 8 日,NCC 通过公视换照和营运计划变更案;自 7 月 6 日起升级 HD 讯号播出,和客家电视台、原住民族电视台并列第四个主频道升级为高清讯号的电视台。 2020 年 6 月 1 日,公视主频改为 24 小时全日播出,收播时间改为每月第 1 个周四 02:00~06:00。 公视台语台(台湾话:Kong-sī Tâi-gí-tâi)是台湾公共电视台旗下的电视频道之一,前身为 2004 年 7 月 1 日开播的“Dimo TV”、以及 2012 年 10 月 1 日更名的“公视 2 台”,2019 年 7 月 1 日改为现名,为台湾第一个以全台语播出的公共性电视频道。 公视 3 台是公共电视文化事业基金会旗下的一个电视频道,也是台湾第一个高清电视频道。由公视接受行政院新闻局“公共广电与文化创意、数字电视发展两年计划”补助建置经营。 2008 年 5 月 15 日睌上 8 点起开始试播,第一个播出的节目为连续剧《美味关系》。2012 年 7 月 24 日正式开播,节目内容则以外国电影、戏曲、文化艺术和体育赛事等为主。创台之初的频道名称为“HiHD”,“Hi”是“招呼”、“迎接”之意,“HD”是“High Definition”(高清)之意。2012 年 8 月 31 日起,频道名称由“HiHD”更改为“公视 HD”。 2016 年 7 月 6 日凌晨两点起更名为“公视 3 台”,定位为体育赛事、艺文、各国剧集的频道。

Taiwan+

为什么要把Taiwan+分离出来说,是因为TaiwanPlus开播于今年 10 月 3 日,而他的开台历程与公视有着密不可分的关系。

Taiwan+(中文:台湾+),又称TaiwanPlus,为影音串流平台。由台湾省文化部设立、中央通讯社主责执行的“国际影音串流平台计划”,正式定名为“TaiwanPlus”,是台湾首个向国际观众宣扬台湾的英语影音新闻和节目的平台,平台于 2021 年 8 月 30 日正式上线。2022 年 6 月 9 日,平台由公共电视文化事业基金会经营,并于 10 月 3 日开播电视频道。

中央社称,TaiwanPlus 是台湾有史以来最大的台湾视讯平台,目的是将台湾的节目、新闻和故事带到全世界,内容设定包括严肃的新闻议题、软性的文化及艺术主题。TaiwanPlus 旨在发出台湾的声音,向英语世界提供区域事件和问题的多媒体报导。 路透社则报导,TaiwanPlus 成立时,正值中国大陆积极透过英语媒界,尤其是透过中国环球电视网(CGTN),向外界传播其观点,并同时在打压台湾的国际空间。

TaiwanPlus建台历史

2020年7月

台湾省文化部便开始委托公视建置英语网络影音平台,规划国际数位传播发展计划,向世界宣告台湾的经验与价值。这个名叫“国际传播数位计划”的前导计划耗资 10 亿元新台币,原计划 2021 年上线,涵盖新闻、节目、专题、纪录片等内容。外界普遍质疑该计划会令公视成为类似于我们大陆的“大外宣”机构,而公视董事冯小非曾一度于 Facebook 贴文抨击执政当局介入公视经营,罔顾公视独立性,就连公视高层也没守住应守防线。多位董事表达不满之下,公视于 7 月 27 日举行临时董事会,最终以 11 票对 4 票通过影音平台计划,时任公视总经理曹文杰、执行副总经理谢翠玉、新闻部经理苏启祯当场辞职抗议。最终,文化部于 29 日宣布终止有关“国际影音平台”委托案,但会另寻执行方式,力争次年 1 月 1 日开播。

2021年5月

该计划最终由中央社承接,正式定名为“TaiwanPlus”由福斯传媒集团亚洲区执行副总裁暨大中华区董事总经理蔡秋安担任执行长。

2021年8月30日

TaiwanPlus 影音串流平台正式上线时,也将由台湾戏剧“斯卡罗”打头阵,同步抢先在海外地区独家首播。

2022年6月9日

TaiwanPlus 与中央社合约到期后,由公视经营。

2022年8月17日

NCC 核准公视新增“TaiwanPlus”服务,以传统的电视频道形式开播,同时于其他电视平台上架,9 月 8 日起于无线数位频号 CH7 进行频道讯号测试,预计于 10 月 3 日开播。

2022年9月14日

中华电信 MOD 新增“TaiwanPlus”频道,于 10 月 3 日免订阅上架。定频于 558 台。

2022年10月3日

正式开台。

台湾省民众最不能接受的是,参与 Taiwan Plus 平台视觉识别系统设计的 JL Design 公司,同样也接了我们的官方媒体中国中央电视台旗下中国中央电视台纪录频道中国环球电视网纪录频道的频道包装设计。 2022 年 2 月,外媒驻台记者 Sam Reynolds 发现,TaiwanPlus 影音平台流量少得可怜,实在未能达到“宣扬台湾”效果。民众党对此批评,该平台无助于把台湾特色行销到世界。Taiwan Plus 软开台(Soft launch)一年后,Taiwan Plus App 下载约十二万次,相较当初设定百万人次,达成率仅一成多,引起国民党立委万美玲质疑。国民党立委林奕华郑正钤亦抨击,TaiwanPlus 的电视频道没有法源依据,“都是政府主导,要什么就要什么,没法源就要硬干”。

我的观点

时至今日,如果站在台湾的角度看问题,公视真的做到了它该做的吗?

答案是确实做到了,从历年来制播表现与获奖记录,公视人为台湾电视留下了很多优秀的节目

我记得前两年,在台语台开台的时候,对 2003 年的戏剧《后山日先照》做了修复,张美瑶确实让我为之流泪;这样的例子很多,《一把青》,《你的孩子不是你的孩子》,《我们与恶的距离》,《生死接线员》,《噬罪者》等优秀的电视剧;《公视电影院,《公视人生剧展》,《学生剧展》,《新创电影》,《听听看》,《有话好说》等一系列节目均出自公视,他会给很多新人机会,也造就了经典,“水果奶奶”应该是许多人的回忆。

另外公视的频道包装也是很好看的,算是很有风格的 ID

如果不被政党介入,那么也就不会有“公视门”事件?

这个东西很难讲,我一个没参加过什么选举的人也不太好说,但有一点,公视确实会受执政党影响,而公视董事会是否能坚持住底线,又或者说公视法能不能保护公视不被外部势力侵入这个需要进一步观察。

如果它绿了,它真的还算中立吗?

从各个节目来看,台湾媒体一直是开放自由的状态,不论你是何种立场,均可以畅所欲言,允许不同的声音才有进步

而你看公视新闻会与其他台会感觉有明显差异,首先英语,越南语,泰语,台语,手语等新闻的播出是一种创新的国际化尝试,新闻内容也不局限于鸡毛蒜皮的小事,主播在播报时也不太会有个人立场的介入,因此算得上中规中矩。

大陆是否有会有全国性的公共媒体?

我觉得不太好说,至少目前这个阶段我觉得先把节目分级制度搞定比较重要,不要一刀切,允许更多的创作自由才有更多优秀的作品。我一直相信我们大陆的电影,电视或者综艺都可以做的更好,只是目前限制条件过多受到影响较大。


最后,希望两岸早日完成和平统一,落叶归根!

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/about-pts/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/about-the-55th-golden-bell-awards/index.html b/posts/about-the-55th-golden-bell-awards/index.html new file mode 100644 index 000000000..eaf784b5d --- /dev/null +++ b/posts/about-the-55th-golden-bell-awards/index.html @@ -0,0 +1,19 @@ +第55届金钟奖相关 | CC的部落格

第55届金钟奖相关

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

第 55 届金钟奖相关

  • 资料来自维基百科,自由的百科全书,根据相关法律法规做了适当修改,坚持一个中国原则,但也遵守 CC BY SA 协议
    第 55 届金钟奖 55th Golden Bell Awards
    日期广播类:2020 年 9 月 19 日电视类:2020 年 9 月 26 日
    地点中国台湾台北市国父纪念馆
    地区中国台湾
    主办单位指导单位:文化部主办单位:文化部影视及流行音乐产业局承办单位:三立电视
    主持人广播:吴玛丽、陈子见电视:白家绮、Gino、曾莞婷、陈冠霖、黄路梓茵、卢广仲、曾国城、炎亚纶
    预展主持人电视类星光大道:黄豪平、李霈瑜
    官方网站gba.tavis.tw
    电视/电台转播
    电视网络广播类:三立电视、Vidol 电视类:三立电视、公视、Vidol
    时长广播类:电视类:
    ← 第 54 届金钟奖第 56 届 →以下中国台湾均称为台湾

第 55 届金钟奖(英语:55th Golden Bell Awards / 55th GBA)是 2020 年台湾传媒业界的年度盛事之一,以表扬 2020 年度杰出的台湾广播电视从业人员,延续过往模式分为广播、电视金钟奖,并均于台北市国父纪念馆举行。广播金钟奖颁奖典礼于 2020 年(民国 109 年)9 月 19 日举行,由吴玛丽陈子见担任典礼主持人;电视金钟奖颁奖典礼于 2020 年(民国 109 年)9 月 26 日举行,由白家绮Gino曾莞婷陈冠霖黄路梓茵卢广仲曾国城炎亚纶三个组合分段担任典礼主持人,黄豪平李霈瑜担任星光大道主持人。

过程

广播

  • 本届广播金钟奖报名时间为 2020 年 4 月 13 日~ 2020 年 5 月 4 日
  • 本届广播金钟奖特别奖推荐时间为 2020 年 4 月 13 日~ 2020 年 6 月 5 日
  • 2020 年 8 月 19 日公布广播金钟奖入围名单。

电视

  • 本届电视金钟奖报名时间为 2020 年 4 月 13 日~ 2020 年 5 月 4 日
  • 本届电视金钟奖特别奖推荐时间为 2020 年 4 月 13 日~ 2020 年 6 月 5 日
  • 2020 年 8 月 26 日公布电视金钟奖入围名单。

广播类入围暨得奖名单

109 年度广播金钟奖颁奖典礼于 2020 年 9 月 19 日于台北市国父纪念馆举行,颁发如下奖项:

节目奖

流行音乐节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《Langdau 原创社》财团法人原住民族文化事业基金会黄子佼、茄子蛋
获奖《Street Voice 未来进行式》飞碟广播股份有限公司
《耳朵借我》财团法人原住民族文化事业基金会
《告白》内政部警政署警察广播电台
《宝岛真无闲》宝岛新声广播电台股份有限公司

类型音乐节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
获奖《Jazz Supreme 爵士‧无所不在》财团法人台北劳工教育电台基金会吴建恒、ABAO 阿爆
《客家妹来打卡》财团法人客家公共传播基金会
《原声探索》财团法人原住民族文化事业基金会
《倾听音乐》财团法人佳音广播电台
《当音乐来敲门》正声广播股份有限公司

教育文化节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《自然笔记》国立教育广播电台王美英、范钦慧
《森林美乐地》汉声广播电台
《笔尖上孩提的奇幻之旅》财团法人中央广播电台
获奖《雁子飞过台三线》财团法人客家公共传播基金会
《余音鸟袅》内政部警政署警察广播电台

儿童节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《i 动物进行式》国立教育广播电台小茱姐姐(施贤琴)、依娜(黄怡馨)、Deborah(李诺亚)
《大脚逛世界》内政部警政署警察广播电台
获奖《地球探险号》国立教育广播电台
《维多叔叔的故事欢乐车》基隆轻松广播电台股份有限公司

少年节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《技职 MVP》国立教育广播电台邵大伦、邱锋泽、陈零九
《青春好好 Young》财团法人富邦文教基金会
《青春创学院》国立教育广播电台
获奖《发现新鲜“市”》内政部警政署警察广播电台
《听青春在唱歌》台北广播电台

社会关怀节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《45 度角的天空》汉声广播电台林书炜、黄博炜
《人生路歌声情》国立教育广播电台
《生命拼图》行政院农业委员会渔业署渔业广播电台
《幸福北台湾》国立教育广播电台
获奖《碍运动》内政部警政署警察广播电台

艺术文化节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《RTI 放映室》财团法人中央广播电台蒋伟文、曲艾玲
《山海族子民》财团法人原住民族文化事业基金会
《世界梦想表演厅》国立教育广播电台
获奖《生活 AGOGO-说在地的故事》全国广播股份有限公司
《声动美术馆》财团法人中央广播电台

生活风格节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《Joy’s Fantasy》财团法人台北劳工教育电台基金会流氓阿德(黄永德)、陈明珠
《世界异家来作客》财团法人客家公共传播基金会
《全世界最亮的光》财团法人中央广播电台
获奖《食随滋味》内政部警政署警察广播电台
《农民食堂开饭了》国立教育广播电台

社区节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《大地采风》正声广播股份有限公司高雄广播电台王美英、范钦慧
《日出的所在》正声广播股份有限公司云林广播电台
《移山倒海樊梨花-Love can move mountains 听见台湾的心跳声》台湾广播股份有限公司
《爱上新竹》竹科广播股份有限公司
获奖《诸罗采风》正声广播股份有限公司嘉义广播电台

广播剧奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
获奖《人生想想剧场》财团法人中央广播电台杨小黎、谢哲青
《大树下听故事》大树下广播电台股份有限公司
《珍女人时代剧场》台北广播电台
《时代剧场》财团法人中央广播电台
《假日听电影》正声广播股份有限公司高雄广播电台

单元节目奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《Cultural Visa Everywhere》财团法人中央广播电台杨小黎、谢哲青
《KISS 旅行台湾的一百种视角》大众广播股份有限公司
获奖《台湾幸福进行曲》好家庭广播股份有限公司
《技职翻转人生》国立教育广播电台
《英文有意思》汉声广播电台

个人奖

流行音乐节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
获奖小树《Street Voice 未来进行式》飞碟广播股份有限公司黄子佼、茄子蛋
内克(吴宇轩)《告白》内政部警政署警察广播电台
邵大伦《宝岛真无闲》宝岛新声广播电台股份有限公司
陈炜智《台湾电影笔记》竹科广播股份有限公司
葛大为《同行相记》台北之音广播股份有限公司

类型音乐节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
获奖徐崇育《Jazz Supreme 爵士‧无所不在》财团法人台北劳工教育电台基金会吴建恒、ABAO 阿爆
陈明珠《客家妹来打卡》财团法人客家公共传播基金会
黎慧芝、管仁健《那些年我们一起唱的歌》财团法人中央广播电台
墨镜哥(甘仲维)《Voice Over 鲜声夺人》汉声广播电台
谭志薏、戴伸峰《弦外之音》财团法人中央广播电台

教育文化节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
王美英《e 啦!原住民》高雄广播电台王美英、范钦慧
府城 lalelin《诗情也绵绵》财团法人中央广播电台
获奖范钦慧《自然笔记》国立教育广播电台
徐凡(徐豫梅)《笔尖上孩提的奇幻之旅》财团法人中央广播电台
杨照(李明骏)《东亚史的关键时刻》台北广播电台

儿童节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
小茱姐姐(施贤琴)《i 动物进行式》国立教育广播电台小茱姐姐(施贤琴)、依娜(黄怡馨)、Deborah(李诺亚)
吴廷宏、吴亦伟、吴蔚恩《唱歌学族语-三猫教你唱 blaq balay》财团法人原住民族文化事业基金会
获奖依娜(黄怡馨)、Deborah(李诺亚)《大脚逛世界》内政部警政署警察广播电台
陈燕柔、邱宇宽《地球探险号》国立教育广播电台

少年节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
Polo(陈歆翰)、柚仔(林品贝)《台湾文武爿》财团法人中央广播电台邵大伦、邱锋泽、陈零九
季洁(蔡宜颖)《技职 MVP》国立教育广播电台
柯华葳、游婷雅《阅读推手》好家庭广播股份有限公司
获奖端端(陈端慧)《青春创学院》国立教育广播电台
郑晴(郑雅卿)、蒋蓉(施旭治)《发现新鲜“市”》内政部警政署警察广播电台

社会关怀节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
世昌(洪世昌)《人生路歌声情》国立教育广播电台林书炜、黄博炜
获奖尚恩(黄彦翔)、倚乐(陈怡蓓)、旁白哥(孙铭宏)、Manga(吴曼嘉)《碍运动》内政部警政署警察广播电台
林书炜、朱芯仪《POP 最正点》台北流行广播股份有限公司
马士(凌士哲)《生命拼图》行政院农业委员会渔业署渔业广播电台
詹婉如《就要听“婉”报》财团法人中央广播电台

艺术文化节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
朱家绮《声动美术馆》财团法人中央广播电台蒋伟文、曲艾玲
林菲《生活 AGOGO-说在地的故事》全国广播股份有限公司
阿俊(徐智俊)、李文玫《客家靓朱玉》财团法人宝岛客家广播电台
获奖端端(陈端慧)《世界梦想表演厅》国立教育广播电台
谢哲青《音乐心旅行》财团法人台北劳工教育电台基金会

生活风格节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
大米(林琼美)《农民食堂开饭了》国立教育广播电台流氓阿德(黄永德)、陈明珠
吴若权《媒事来哈啦》财团法人富邦文教基金会
获奖流氓阿德(黄永德)《全世界最亮的光》财团法人中央广播电台
舞赛.古拉斯《岛屿文创村》财团法人原住民族文化事业基金会
苏筠、果果《食随滋味》内政部警政署警察广播电台

社区节目主持人奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
朱卫茵《周末生活女王-低碳环保乐》飞碟广播股份有限公司王美英、范钦慧
思安(陈思安)《幸福藏宝图》正声广播股份有限公司
洪惠冠、蔡荣光《爱上新竹》竹科广播股份有限公司
获奖杨长顺《日出的所在》正声广播股份有限公司云林广播电台
靓慧(王靓慧)《大地采风》正声广播股份有限公司高雄广播电台

企划编撰奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
士玶(黄士玶)、赖可(赖冠宇)、露西(陈珮茹)、俊孝(林俊孝)、罄榆(林罄榆)《一心一艺》内政部警政署警察广播电台杨小黎、谢哲青
内克(吴宇轩)、Vicky(刘虹钰)、Amy(丁宛臻)《告白》内政部警政署警察广播电台
获奖奇林 Michael(林祺宏)、徐凡(徐豫梅)、董娘(董丽琴)、林彦伯、黄裕元、林佩蓉、Joey(刘怡彣)、咪可 Miko(李虹靓)《宝岛记事簿》国立教育广播电台
洁枫(尹洁枫)、叶国新 Jacky(陈昱豪)、刘碧薇 李易澄《东西有艺鉴》内政部警政署警察广播电台
郑立明、廖南瑛《青年转动全球》国立教育广播电台

音效奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
成春福《Cultural Visa Everywhere》财团法人中央广播电台杨小黎、谢哲青
获奖吴坤龙、蔡怡雯、林宪𬭎《假日听电影》正声广播股份有限公司高雄广播电台
李可《听!是谁在歌唱》高雄广播电台
徐进辉、郑惠文 沈逸华、张贺杰《大树下听故事》大树下广播电台股份有限公司
陈文彬《珍女人时代剧场》台北广播电台

广告奖

商品类广告奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《床的世界-上床篇》灰姑娘音乐制作有限公司夜猫 DJ Dennis、阿达、HowHow 陈孜昊
获奖《昇达轮胎无所不在 一路向前守护全台》正声广播股份有限公司台北广播电台
《高雄观音山金宝塔-阿兄篇》王子音乐出版社
《抢银行篇》环球七福广告有限公司
《挤身上流篇》财团法人台北劳工教育电台基金会

非商品类广告奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《POP Radio 防疫广告【清洁队员】篇》台北流行广播股份有限公司夜猫 DJ Dennis、阿达、HowHow 陈孜昊
《防疫大作战之今年七夕不相会篇》正声广播股份有限公司云林广播电台
获奖《防疫宣导》灰姑娘音乐制作有限公司
《环宇公益广告-最美距离篇》环宇广播事业股份有限公司
《关怀老人篇》台南知音广播股份有限公司

电台奖

电台品牌行销创新奖

入围/得奖作品制作公司/广播公司颁奖嘉宾
《【永远的流行乐之王 Michael Jackson 逝世十周年 纪念特辑】》财团法人台北劳工教育电台基金会夜猫 DJ Dennis、阿达、HowHow 陈孜昊
获奖《【疫情平安 一起平安】广播与数位专题影音展》好家庭广播股份有限公司
《超级大喇叭:宝岛逗相挺》大千广播电台股份有限公司

创新研发应用奖

入围/得奖者入围/得奖作品制作公司/广播公司颁奖嘉宾
内政部警政署警察广播电台《广播“视”界魅力无限 社群媒体聚合平台应用》内政部警政署警察广播电台夜猫 DJ Dennis、阿达、HowHow 陈孜昊
获奖国立教育广播电台《数字化广播体验-麦宝电波行动录音室》国立教育广播电台
蔡明佑、李明勋、谢锦隆《广播站台视觉与环境管理发展技术应用》汉声广播电台
郑明祈、吴国钦、陈俊谕《因应疫情之异地主播室系统设计》行政院农业委员会渔业署渔业广播电台

特别贡献奖

得奖者
从缺
  • 109 年度电视金钟奖颁奖典礼于 2020 年 9 月 26 日于台北市国父纪念馆举行,颁发如下奖项:[2] 引言人:于美人以下是追思电视人的名单:

电视类入围暨得奖名单

节目奖

戏剧节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司瞿友宁、贾静雯
获奖《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司
《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司 台湾大哥大股份有限公司
《噬罪者》财团法人公共电视文化事业基金会、兴扬电影有限公司
《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司

迷你剧集奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司许杰辉、锺欣凌
《罪梦者》新加坡商棱聚传播有限公司台湾分公司
《糖糖 Online》财团法人公共电视文化事业基金会、列夫特文化有限公司

电视电影奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
公视人生剧展—《残值》英杰哆股份有限公司许杰辉、锺欣凌
公视迷你电影院—《钉子花》财团法人公共电视文化事业基金会、心艺电影工作室
《住户公约第一条》镜文学股份有限公司
客家电视电影院—《大桔大利 阖家平安》泰尹传播有限公司
获奖新创电影短片 《大吉》寓言工作室

自然科学纪实节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《台湾的前世今生》壹传媒电视广播股份有限公司李明璁、吴奕蓉
《爸!妈!今天吃什么?》台湾优视媒体科技股份有限公司
《原味好时尚》花点心师有限公司
获奖《消失的王者》东森电视事业股份有限公司
《福卫七号 太空任务》台湾电视事业股份有限公司

人文纪实节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖《ivucung 谁谜了路》财团法人原住民族文化事业基金会李明璁、吴奕蓉
《世界新天目》有时电影有限公司
《活力新故乡》客家电视台、八方汇盈数位制作股份有限公司
《纪录观点》财团法人公共电视文化事业基金会
《谁来晚餐 11》财团法人公共电视文化事业基金会

儿童少年节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《kakudan 时光机》财团法人原住民族文化事业基金会严艺文、吴以涵
获奖《出发骑幻岛》财团法人公共电视文化事业基金会、五够赞股份有限公司
《台湾特有种》财团法人公共电视文化事业基金会
《青春爱读书》财团法人慈济传播人文志业基金会
《神奇故事屋》米迦勒传播事业股份有限公司

生活风格节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《地球的庆典》爱尔达科技股份有限公司倪子钧、唐绮阳
获奖《我在市场待了一整天》财团法人公共电视文化事业基金会
《无事坐巴士》财团法人公共电视文化事业基金会—公视台语台
《跟着 dapin 去旅行》财团法人原住民族文化事业基金会
《台湾好味道 足好食台湾味》中华电视股份有限公司

综艺节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《台湾金颂》财团法人公共电视文化事业基金会、奇妙创造股份有限公司黄子佼、蓝心湄
《音乐万万岁 第 4 号作品》财团法人公共电视文化事业基金会
《话山话水话玲珑》财团法人公共电视文化事业基金会—公视台语台 全能制作股份有限公司
获奖《综艺大热门》三立电视股份有限公司、好看娱乐制作股份有限公司
《声林之王 声境传奇》量子娱乐制作股份有限公司

益智及实境节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《一字千金斗字英雄会》财团法人公共电视文化事业基金会、全能制作股份有限公司黄子佼、蓝心湄
获奖《全民星攻略》友松娱乐股份有限公司
《全家有智慧》财团法人公共电视文化事业基金会—公视台语台、三凤有限公司
《阮三个 2》财团法人公共电视文化事业基金会、用力拍电影有限公司

动画节目奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖《FOOD 超人第二季》财团法人公共电视文化事业基金会、风车图书出版有限公司严艺文、吴以涵
《小儿子系列动画第三季:快乐》梦田影像股份有限公司
《音乐关键字—寻声》客家电视台
《海精灵马努依》靖天传播国际事业股份有限公司、原金国际有限公司
《树人大冒险》财团法人原住民族文化事业基金会

个人奖

戏剧节目男主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖姚淳耀《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司龙劭华、蔡昌宪
张孝全《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司、台湾大哥大股份有限公司
庄凯勋《噬罪者》财团法人公共电视文化事业基金会、兴扬电影有限公司
许光汉《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司
蔡昌宪《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司

戏剧节目女主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
天心《最佳利益》群之噰传播有限公司、黑剑电视节目制作股份有限公司张孝全、王柏杰
林玟谊《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司
获奖柯佳嬿《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司
莫允雯《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司
杨谨华《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司

戏剧节目男配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
侯彦西【鄢胜宇】《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司庄凯勋、莫允雯
获奖马力欧《国际桥牌社》马克吐温国际影像有限公司
曹晏豪《噬罪者》嘉扬电影有限公司、财团法人公共电视文化事业基金会
杨烈《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司
蔡阿炮【蔡明毅】《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司

戏剧节目女配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李劭婕客家寻味剧场—《乌阴天的好日子》春河剧团事业有限公司庄凯勋、莫允雯
李璇【朱继屏】《大林学校》财团法人慈济传播人文志业基金会、北投映像电影有限公司
袁艾菲《我们不能是朋友》八大电视股份有限公司、友松娱乐股份有限公司
获奖蔡淑臻《噬罪者》嘉扬电影有限公司、财团法人公共电视文化事业基金会
谢琼煖《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司

戏剧节目最具潜力新人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
何佩芸《忠孝节义》台湾电视事业股份有限公司、丽生百合国际娱乐股份有限公司傅孟柏、李沐
获奖李沐《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司、台湾大哥大股份有限公司
夏大宝《噬罪者》嘉扬电影有限公司、财团法人公共电视文化事业基金会
瑭霏《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司
刘韦辰HIStory3 《那一天》巧克科技新媒体股份有限公司

迷你剧集/电视电影男主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
洪都拉斯【洪勝德】公视人生剧展—《盲人阿清》深邃电影有限公司杨谨华、天心
张孝全《罪梦者》新加坡商棱聚传播有限公司台湾分公司
莫子仪《追凶 500 天》柒拾陆号原子股份有限公司、台湾大哥大股份有限公司、偶数创意工作室
陈竹升公视人生剧展—《残值》英杰哆股份有限公司
获奖游安顺新创电影短片 《大吉》寓言工作室

迷你剧集/电视电影女主角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
小薰【黄瀞怡】《追凶 500 天》柒拾陆号原子股份有限公司、台湾大哥大股份有限公司、偶数创意工作室杨谨华、天心
吴以涵《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司
获奖吴奕蓉客家电视电影院-《大桔大利 阖家平安》客家电视台、泰尹传播有限公司
李又汝《无主之子》民间全民电视股份有限公司、列夫特文化有限公司
谢盈萱《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司

迷你剧集/电视电影男配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
太保公视人生剧展—《残值》英杰哆股份有限公司莫子仪、小薰
王柏杰《罪梦者》新加坡商棱聚传播有限公司台湾分公司
孙绽《无主之子》民间全民电视股份有限公司、列夫特文化有限公司
获奖游安顺公视人生剧展-《盲人阿清》深邃电影有限公司
廖钦亮新创电影短片-《大吉》寓言工作室

迷你剧集/电视电影女配角奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
丁宁公视人生剧展-《残值》英杰哆股份有限公司莫子仪、小薰
范晓萱《罪梦者》新加坡商棱聚传播有限公司台湾分公司
杨丽音《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司
谢欣颖《住户公约第一条》镜文学股份有限公司
获奖琇琴【于子育】《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司

迷你剧集/电视电影最具潜力新人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖白小樱《住户公约第一条》镜文学股份有限公司傅孟柏、李沐
吴静依公视学生剧展《乐园 Somewhere Out There》曜演影视制作有限公司、财团法人公共电视文化事业基金会
林书函公视学生剧展《乐园 Somewhere Out There》曜演影视制作有限公司、财团法人公共电视文化事业基金会
陈莎莉公视学生剧展—《入世》电光影里影业有限公司、财团法人公共电视文化事业基金会
睦媄公视人生剧展—《风中浮沉的花蕊》大吉祥整合行销有限公司、财团法人公共电视文化事业基金会

戏剧节目导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李岳峰、张志鸿《苦力》财团法人公共电视文化事业基金会、禾丰传播有限公司瞿友宁、贾静雯
李权洋、郑文堂《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司
获奖高炳权、曾英庭《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司
庄绚维、陈冠仲《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司 台湾大哥大股份有限公司
黄天仁《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司

迷你剧集/电视电影导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖林志儒客家电视电影院—《大桔大利 阖家平安》客家电视台、泰尹传播有限公司许杰辉、锺欣凌
赖建颖公视迷你电影院—《钉子花》财团法人公共电视文化事业基金会、心艺电影工作室
薛朝辉公视人生剧展—《盲人阿清》深邃电影有限公司
严艺文、陈长纶《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司
靳家骅新创电影短片 《大吉》寓言工作室

戏剧节目编剧奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
梁舒婷、徐瑞良《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司、台湾大哥大股份有限公司林昱伶、阮光民
陈洁莹、黄宣颖、萧译玮《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司
杨念纯《噬罪者》财团法人公共电视文化事业基金会、兴扬电影有限公司
郑心媚《镜子森林》民间全民电视股份有限公司、绿光全传播有限公司
获奖简奇峯、林欣慧《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司

迷你剧集/电视电影编剧奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
林志儒、刘存菡客家电视电影院—《大桔大利 阖家平安》客家电视台、泰尹传播有限公司许杰辉、锺欣凌
蔡俊彬、刘宇公视人生剧展—《残值》英杰哆股份有限公司
薛朝辉公视人生剧展-《盲人阿清》深邃电影有限公司
严艺文、范芷绮 黄小猫【黄馨萱】《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司
获奖靳家骅新创电影短片—《大吉》寓言工作室

自然科学及人文纪实节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖吴秀梅 Siku Sawmah《原味好时尚》花点心师有限公司李明璁、吴奕蓉
吴奕蓉《花漾同学会》客家电视台、和展影视股份有限公司
许效舜《在台湾的故事》三立电视股份有限公司
舒梦兰《消失的王者》东森电视事业股份有限公司
詹怡宜《一步一脚印 发现新台湾》联利媒体股份有限公司

儿童少年节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
获奖Buya【陈宇】、Pagnoyod【锺家骏】《kakudan 时光机》财团法人原住民族文化事业基金会严艺文、吴以涵
阿松【纪竣崴】、纪昀希《出发骑幻岛》财团法人公共电视文化事业基金会、五够赞股份有限公司
郭彦均、锺欣凌《超级总动员》东森电视事业股份有限公司、全富传播股份有限公司
陈玮薇《小主播看天下 WOW!》财团法人慈济传播人文志业基金会
谢哲青《青春爱读书》财团法人慈济传播人文志业基金会

生活风格节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
Alana【郑雅文】《Follow Alana 爱游世界》晴雅数位传播股份有限公司倪子钧、唐绮阳
王晓书、陈濂侨《听听看》财团法人公共电视文化事业基金会
获奖高怡平《家庭八点档转转发现爱》米迦勒传播事业股份有限公司
梦多【大谷主水】《地球的庆典》爱尔达科技股份有限公司
蓝心湄《女人我最大》联利媒体股份有限公司

综艺节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
吴宗宪 、陈汉典、LULU【黄路梓茵】《综艺大热门》三立电视股份有限公司、好看娱乐制作股份有限公司黄子佼、蓝心湄
获奖浩子【谢炘昊】、乱弹阿翔【陈泰翔】《台湾金颂》财团法人公共电视文化事业基金会、奇妙创造股份有限公司
许效舜《疯神无双》香港商福斯传媒有限公司台湾分公司
曾国城、巴钰《一袋女王》香港商福斯传媒有限公司台湾分公司

益智及实境节目主持人奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
胡瓜【胡自雄】、玛莉亚【叶欣眉】《欢乐智多星》香港商福斯传媒有限公司台湾分公司黄子佼、蓝心湄
获奖曾国城、蔡尚桦《全民星攻略》友松娱乐股份有限公司
黄子佼、吴姗儒《一呼百应之揪团大考验》财团法人公共电视文化事业基金会
杨贵媚、SOAC【刘永伟】、范少勋《阮三个 2》财团法人公共电视文化事业基金会、用力拍电影有限公司

技术类奖项

非戏剧类节目导演奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
江国梁、黄至琦、谢光诚《世界新天目》有时电影有限公司杨丽音、琇琴【于子育】
林名远《我,存在 —原住民影像纪录 Ta’u 存在》财团法人原住民族文化事业基金会
林慧芬、李文鸿《似水华年—那年盛夏的花火》财团法人慈济传播人文志业基金会
获奖柯金源《纪录观点 神殿》财团法人公共电视文化事业基金会
刘嵩《农村的远见 第二季》宝花传播有限公司

非戏剧类节目导播奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
丁光慈《上奅 台湾歌》中华电视股份有限公司、异象国际传播有限公司杨丽音、琇琴【于子育】
吴佩谕《声林之王 声境传奇》量子娱乐制作股份有限公司
获奖李丽芳《第 15 届 KKBOX 风云榜颁奖典礼》台湾电视事业股份有限公司
梁远毅《音乐万万岁 第 4 号作品》财团法人公共电视文化事业基金会
陈星凤《台湾金颂》财团法人公共电视文化事业基金会、奇妙创造股份有限公司

戏剧类节目摄影奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
江敏忠《极道千金》好好电影工作室有限公司、新加坡商满满哆股份有限公司许效舜、马力欧
李清迪、刘至桓、詹嘉文《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司
获奖周宜贤、杨丰铭、孙纪明《罪梦者》新加坡商棱聚传播有限公司台湾分公司
马华【冯信华】《住户公约第一条》镜文学股份有限公司
刘至桓《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司 台湾大哥大股份有限公司

非戏剧类节目摄影奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
江国梁、刘吉雄、刘建伟《世界新天目》有时电影有限公司杨丽音、琇琴【于子育】
何明瑞、吴政儒《农村的远见 第二季》宝花传播有限公司
吴佳明、张祥昱《真世代—移动中的温暖》鑫隆多媒体股份有限公司
获奖陈锦亮、梁勇光、周劭杰 刘志雄、刘燕樟《我在市场待了一整天》财团法人公共电视文化事业基金会
廖敬尧、施蓝波安、吴佳明 胡登贺《艺术很有事》财团法人公共电视文化事业基金会

戏剧类节目剪辑奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
林姿妤、张雅婷公视人生剧展 —《残值》英杰哆股份有限公司许效舜、马力欧
获奖林政宏《俗女养成记》中华电视股份有限公司、百戏电影制作有限公司
张雅婷公视新创电影《4 X相识—前世情人的情人》十三行娱乐国际有限公司、财团法人公共电视文化事业基金会
解孟儒、江翊宁《谁是被害者》良人行影业有限公司、瀚草影视文化事业股份有限公司 台湾大哥大股份有限公司
潘客印《肇事者逃逸》镜文学股份有限公司

非戏剧类节目剪辑奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
王瀚德《我在市场待了一整天》财团法人公共电视文化事业基金会杨丽音、琇琴【于子育】
获奖滕兆锵《真世代-妈祖住我家》鑫传视讯广告股份有限公司、鑫隆多媒体股份有限公司
谢欣志《似水华年—如常》大逆光影音制作有限公司
苏志宗《纪录观点 神殿》财团法人公共电视文化事业基金会
粘瓈文《真世代—移动中的温暖》鑫传视讯广告股份有限公司、鑫隆多媒体股份有限公司

声音设计奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
Thomas Foguenne 福多玛 黄年永、杨子介、陈奕伶《76 号恐怖书店之恐惧罐头》柒拾陆号原子股份有限公司、台湾大哥大股份有限公司 十只手指电影制作所有限公司许效舜、马力欧
Thomas Foguenne 福多玛 戴志光《纪录观点 神殿》财团法人公共电视文化事业基金会
获奖高伟晏、郑元凯、许家维 黄镇洋、汤湘竹《罪梦者》新加坡商棱聚传播有限公司台湾分公司
陈建骐、罗恩妮、叶约瑟 王逸勋、邱昇元、陈炫宇 王令翔、庄钧智、唐诗婷 Thomas Andrew Matthews《你那边怎样·我这边 OK》拙八郎创意执行股份有限公司、台湾电视事业股份有限公司 八大电视股份有限公司
黎明鑫《声林之王 声境传奇》量子娱乐制作股份有限公司

灯光奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
李元岳《音乐万万岁 第 4 号作品》财团法人公共电视文化事业基金会许效舜、马力欧
蔡明钗公视学生剧展 —《九孬》早雨早晴影像有限公司
郑得寿公视人生剧展 —《残值》英杰哆股份有限公司
获奖谢松铭《罪梦者》新加坡商棱聚传播有限公司台湾分公司
魏琥弦公视新创电影《4 X相识 —前世情人的情人》十三行娱乐国际有限公司、财团法人公共电视文化事业基金会

美术设计奖

入围/得奖者入围/得奖作品制作公司/电视公司颁奖嘉宾
二马【冯建彰】《声林之王 声境传奇》量子娱乐制作股份有限公司许效舜、马力欧
元述 【廖建安】、施筱柔 储旭【储榢逸】、郭宪聪《谁是被害者》良人行影业有限公、瀚草影视文化事业股份有限公司 台湾大哥大股份有限公司
获奖梁硕麟、施筱柔《罪梦者》新加坡商棱聚传播有限公司台湾分公司
廖晏舟、黄嬿莼《用九柑仔店》三立电视股份有限公司、香港商福斯传媒有限公司台湾分公司 华人创作股份有限公司、鹿路电影有限公司 内容物数位电影制作有限公司
刘蕙屏、林芷妤公视新创电影《4 X相识—前世情人的情人》十三行娱乐国际有限公司、财团法人公共电视文化事业基金会

节目创新奖

入围/得奖作品制作公司/电视公司颁奖嘉宾
《一呼百应之揪团大考验》财团法人公共电视文化事业基金会林昱伶、阮光民
公视新创电影《4 X相识-前世情人的情人》财团法人公共电视文化事业基金会、十三行娱乐国际有限公司
《全家有智慧》财团法人公共电视文化事业基金会-公视台语台、三凤有限公司
获奖《我在市场待了一整天》财团法人公共电视文化事业基金会
获奖《想见你》香港商福斯传媒有限公司台湾分公司、三凤有限公司

特别奖

终身贡献奖

得奖者引言人颁奖嘉宾
陈丽如(小凤仙) 林正雄(林义雄)陈亚兰陈亚兰 李永得

追思逝世电视人

表演节目

广播金钟

表演嘉宾演出主题演出内容
LEO 王、孙盛希、宇宙人从广播开始较劲LEO 王〈快乐的甘蔗人〉 孙盛希〈暧〉 宇宙人〈陪我玩 Play One〉 Why Not〈无法度按捺〉
唐从圣、李维真、黄大谦有本事才敢大声电视人.广播人.网络人
荒山亮、戴爱玲因为你我会更强黄妃〈追追追〉 萧敬腾〈王妃〉 张惠妹〈好胆你就来〉 林强〈春风少年兄〉

电视金钟

表演嘉宾演出主题演出内容
龚钰祺、吴曜宇、台北爱乐青年管弦乐团欢迎来到金钟奖演奏曲目: 徐佳莹〈极限〉 苏打绿〈你在烦恼什么〉 五月天〈盛夏光年〉 孙燕姿〈逆光〉
Lulu 黄路梓茵、卢广仲这是我的舞台卢广仲〈二十四小时柒天〉 Lulu 黄路梓茵〈赖床公主〉 卢广仲〈OH YEAH!!!〉
大支梦想就要起飞大支〈对手 Opponent〉

评审名单

广播金钟奖评审名单

主任委员
田定丰
特别奖主任委员
袁韵婕

电视金钟奖评审名单

主任委员
瞿友宁
戏剧节目
陈世杰(召集人)、尹馨、吴慷仁、姜秀琼、施立、陈和榆、傅凯羚、黄世鸣、郑秉泓、瞿友宁、吕莳媛
迷你剧集/电视电影
李亚梅(召集人)、王识贤、林正盛、姚坤君、曾英庭、黄健玮、温郁芳、廖士涵、刘梓洁
自然科学纪实节目/人文纪实节目
黄惠侦(召集人)、李美仪、麦觉明、冯贤贤、阎鸿亚
儿童少年节目
唐台龄(召集人)、何琦瑜、赵婷
生活风格节目
王浩一(召集人)、吴凤、李霈瑜、唐绮阳、曾宝仪
综艺节目/益智及实境节目
陈亚兰(召集人)、李景白、柴智屏、许杰辉、陈敬宗、赖勋彪、谢哲青
动画节目
纪柏舟(召集人)、郭宪聪、刘绮珊
技术奖
贺照缇(召集人)、吴若昀、李惠仁、胡定一、许世明
特别奖主任委员
梁修身
特别奖评审委员

金钟奖制作团队

广播金钟

  • 109 年度广播金钟奖
  • 指导单位:文化部
  • 主办单位:文化部影视及流行音乐产业局
  • 承办单位:三立电视
  • 总监制:张荣华
  • 节目统筹:王淑娟
  • 专案统筹:高明慧
  • 专案管理:李君顺、陈幼庭、黄昰桦、张彦筠、刘亭之、刘恩佑、叶映汝、吕筱玮
  • 行销/海外行销统筹:谢慰雯
  • 行销协力:邬嘉绫、刘立平、陈志昇、蔡佩瑜、张若琪、苏贞婷、李宜馨、黄歆雅、林柏昱、林筱涵
  • 工程统筹:龚美富
  • 新媒统筹:蓝宜祯、洪采岑
  • 新媒协力:黄廷宏、熊鸿斌、苏欣伟、黄立凯、王巽基、翁堃泰、连雅卉、蔡孟轩、姜淑龄、李宜倩、黄昱颖、曾丽洋、陈怡君、王俪颖、彭立扬、倪嘉达、陈姿颖、许巧妮、吴冠毅
  • 数位媒体工程:陈敬昌、陈玉菁、庄裕铭、刘元纮、朱俊德、吴鸿中、陈登隆、李佳祥、江佩芬
  • 资讯传输设计:耿履夷、王士方、陈俊宏、陈荣杰、詹志全
  • 讯号后制统筹:苏玠玺
  • 行政统筹:张维铭
  • 行政协力:张志雄、李盈蒨、颜银南、孙楷泽、苏珮雯、林惠淳、陈淑卿、纪玉芬、萧振文、刘謦嘉、林友三、温崇铭、童振瑞、陈维纲、陈诗涵、苏振邺、蔡宛婷
  • 赞助统筹:胡闵雯
  • 赞助协力:黄惠芬、陈慧娟、吕启源、曾凡珊、刘建呈、游智淳、施明志、林耘谊、张家豪、林珮𫓹、陈宥亘、蔡宗翰、吴佩宜、曾子萱、杨仁杰、周语铃、陈奇汉、郑湘桦、吴书菱、黄佳芳、邓文馨、蔡伊镕、董依𬭚
  • 109 年度广播金钟奖颁奖典礼
  • 总监制:王淑娟
  • 执行监制:黄晓玫
  • 典礼制作人:谢孟芬
  • 典礼制作群:王梦黛、邱湘莹、张伶卉、周矩源、林君谕、林孟如、吴亚桦、杨雅斐、王韵慈、杨治娟、陈钲锠、胡馥纯、吴佳颖、简婉如、王建棠、锺孟洁、陈奕颖、蔡妏雪、黄佳雯、周倢羽、黄至柔、邱亭瑄、许崇豪、苏子晴、蓝敬淇、李晨瑜、谢欣妤、林芳玉、锺欣惠、苏圣棋、江政颖、洪辰嫣、锺衣雯、凃嘉文、周妍廷、陈诗涵、沈美仪、陈淑卿、董依𬭚、苏振邺、孙楷泽、赖玉婷、陈怡静、洪维信、杨雁捷、张韶恩、梁永青、梁家豪、林雅婷、李东元、蔡青萦、叶为诚、程仁伟、陈钰雯、凌静宜、许芳瑜、林友三、曹美琳、范振轩、黄雅文、陈宥亘、黎莉、田筱琪、蔡宗翰、郑宇彤、廖翊婷、曾译卉、叶子瑄、王怡钧、陈怡如、郭柏旸、徐弦纭、徐嘉妤、邱苡洁、周亮辰、陈信智、曾琴
  • 主持人:玛丽
    • 化妆:牙牙
    • 发型:罗南
    • 造型:淘乐思造型有限公司 Doris
    • 服装:JillBridal 吉儿法式手工婚纱
    • 珠宝:PIAGET 珠宝
  • 主持人:视网膜
    • 发型:好剪才
    • 化妆:吴国铭
    • 服装:Hugo Boss、Leisure Bespoke 立沐杉订制西服
    • 手表:BREITLING 百年灵
    • 眼镜:骏艺光学
  • 特别感谢:飞碟电台 光禹
  • 典礼司仪:马克(沈子煜)
  • 典礼音乐:阿毛老师
  • 典礼视觉
  • 视觉统筹:黄晓玫
  • 平面设计:邱孟彦、邱清顺、刘颖铮、陈彦蓁
  • 动画设计:张恒芸、王圣竹、林宇轩、谢欣贤、邱云星、曾彦祯
  • 影像处理:林声
  • 三立工程
  • 工程统筹:龚美富
  • 导播:吴美君
  • 现场指导:邱雅玲、李紫瑀、黄雅琳、柯君颖
  • 助理导播:翁逸玫、张成柔、王薏宁、李孟洁
  • 技术指导:陈建良
  • 视讯工程师:刘世裕、赵德昇
  • 视讯助理:张元威、王通燊
  • 摄影师:潘铭义、王书镇、沈仪铭、陈俊谊、王薪智、江政谦、林明雄、豊世颖、陈俊雄、吴思宸、黄春镇、杜彦翔、林文陞、林岢霈
  • 灯光师:王文枫、林中强、邱汉忠、李智伟
  • 成音师:孟兆欣、叶志忠、夏永柠、罗梵笠、蔡豊泽、陈文隆
  • 后制统筹:苏玠玺
  • 剪辑指导:薛宇琳、许佳雯
  • 后制剪辑:范志明、吴鸿伟、赖庆原、黄珮瑜、李幸蓉、陈美绍、史昇鑫、张君豪
  • 影片制作:郑亨泰、古淑慧、巫少强、廖昱凯、杨治娟、黄雅新、吴佳颖、黄建国、林思婷、简婉如、李晨瑜
  • 影片音效:声都传播有限公司
  • 影片旁白:马克(沈子煜)
  • 影片灯光:邱汉光
  • 影片摄影:外景摄影组
  • 视觉总监:提摩西
  • 影像统筹:提摩西影像
  • 平面视觉指导:卢奕桦、刘昱贤
  • 印刷设计:卢奕桦、刘昱贤
  • 平面专案经理:牛子齐
  • 平面设计:卢奕桦、刘昱贤
  • 专刊设计:王祥薇、刘昱贤
  • 标准字设计:赵家祺
  • 动画导演:提摩西
  • 专案经理:刘颖仁
  • 视觉设计:提摩西
  • 3D 设计师:提摩西、黄靖杰、吴嘉进、黄俊安、柯明延、赖俊杰、许福强、李明学、李慧宁
  • 标准字动态制作:詹游承
  • 循环动画制作:提摩西、詹游承
  • 镜面设计:詹游承
  • 奖项模板制作:提摩西
  • 音乐总监:林昀骏、黄镇洋
  • 音乐/音效制作:林昀骏、黄镇洋、林柏勲、蔡昀熹
  • 乐手演出参与:龙俊宇
  • 表演《从广播开始较劲》
  • 音乐总监:米奇林、鲁纲宇
  • 编曲:鲁纲宇
  • 执行助理:森铭
  • 演出节目制作执行:玩角创意娱乐制作
  • Leo 王工作团队
    • 演唱:王之佑 Leo 王
    • 鼓手:高飞
    • 贝斯手:瑜友桢
    • 吉他:李权哲
    • 键盘/合成器:张汎宇
    • 萨克斯风:高杰
    • 长号:胡世汉
    • 小号:甘克蓝
    • 合声:布兰地、薛诒丹
  • 孙盛希工作团队
    • 造型:陈怡安、邱贞瑜
    • 妆/发:Claire、Edmund@Zoom Hairstyling
    • 珠宝:Tiffany&Co.、江怡婷、林明鸿(保全)
    • 服装:Off-White Marine Serre Onefifteen 初衣食午 Charles&Keith
    • 编舞:贾皓钧
    • 编舞助理:马韵婷
    • 舞者:吴立丽、陈慧文、翁蕊、林采乐、张家玲、阮靖容、沃 创意整合、MerryMonarc Dance Studio
  • 宇宙人工作团队
    • 演出者:宇宙人
    • 主唱兼键盘手:小玉
    • 吉他手:阿奎
    • 贝斯手:方 Q
    • 鼓手:小胖
    • Percussion:嘉富
    • PGM:小富
  • 表演《有本事才敢大声》
  • 表演者:唐从圣、李维真、黄大谦
  • 撰稿:刘沿玱
  • 特别感谢:警察广播电台 尚恩
  • 表演《因为你我会更强》
  • 表演者:荒山亮、戴爱玲
  • 编曲制作:无限愿景音乐工作室
  • 编曲:洪敬尧
  • MIDI PGM:林乐伟
  • 吉他:Joel Voo
  • 贝斯:游仁杰
  • 鼓:杨凯淋
  • 合声:靛蓝音程工作室、范品颐
  • 演出节目制作执行:玩角创意娱乐制作
  • 幕后团队
  • 硬件统筹:必应创造
  • 硬件执行:廖志杰、周俊奇、甯钰琇、邱钰雯、许竣杰
  • 舞台设计:李信兴、郑皓心、黄孟莹
  • 灯光工程/音响工程/视讯工程:必应创造
  • 舞台工程:铨闳有限公司
  • 机关工程:奎比克动能系统有限公司
  • 结构工程:铉仪股份有限公司
  • 电力工程:鸿州企业有限公司
  • 会场布置:巨蛋展览股份有限公司
  • 媒体协办:Vidol、MTV、三立新闻网、LINE TODAY 、好事联播网
  • 赞助单位:中华电信、LEXUS、一家人益生菌洗发精、ILING 彩妆造型、iShine 爱闪耀、五洲制药、舒跑 S、台湾中油股份有限公司、可夫莱精品坚果、台湾啤酒
  • 特别感谢:中国台湾广播商业同业公会、GRANDEN、柴语录、YouTube、国父纪念馆
  • 制作、著作:三立电视
  • 委制:文化部影视及流行音乐产业局

电视金钟

  • 109 年度电视金钟奖
  • 指导单位:文化部
  • 主办单位:文化部影视及流行音乐产业局
  • 承办单位:三立电视
  • 总监制:张荣华
  • 节目统筹:王淑娟
  • 专案统筹:高明慧
  • 专案管理:李君顺、陈幼庭、黄昰桦、张彦筠、刘亭之、刘恩佑、叶映汝、吕筱玮
  • 行销/海外行销统筹:谢慰雯
  • 行销协力:邬嘉绫、刘立平、陈志昇、蔡佩瑜、张若琪、苏贞婷、李宜馨、黄歆雅、林柏昱、林筱涵
  • 工程统筹:龚美富
  • 新媒统筹:蓝宜祯、洪采岑
  • 新媒协力:黄廷宏、熊鸿斌、苏欣伟、黄立凯、王巽基、翁堃泰、连雅卉、蔡孟轩、姜淑龄、李宜倩、黄昱颖、曾丽洋、陈怡君、王俪颖、彭立扬、倪嘉达、陈姿颖、许巧妮、吴冠毅
  • 数位媒体工程:陈敬昌、陈玉菁、庄裕铭、刘元纮、朱俊德、吴鸿中、陈登隆、李佳祥、江佩芬
  • 资讯传输设计:耿履夷、王士方、陈俊宏、陈荣杰、詹志全
  • 讯号后制统筹:苏玠玺
  • 行政统筹:张维铭
  • 行政协力:张志雄、李盈蒨、颜银南、孙楷泽、苏珮雯、林惠淳、陈淑卿、纪玉芬、萧振文、刘謦嘉、林友三、温崇铭、童振瑞、陈维纲、陈诗涵、苏振邺、蔡宛婷
  • 赞助统筹:胡闵雯
  • 赞助协力:黄惠芬、陈慧娟、吕启源、曾凡珊、刘建呈、游智淳、施明志、林耘谊、张家豪、林珮𫓹、陈宥亘、蔡宗翰、吴佩宜、曾子萱、杨仁杰、周语铃、陈奇汉、郑湘桦、吴书菱、黄佳芳、邓文馨、蔡伊镕、董依𬭚
  • 109 年度电视金钟奖星光大道
  • 总监制:王淑娟
  • 星光大道执行监制:黄晓玫
  • 星光大道制作人:许蕙茹
  • 星光大道制作群:邱湘莹、张伶卉、林君谕、周矩源、林孟如、吴亚桦、胡馥纯、廖亭琇、王芷晴、许芳瑜、袁锦仪、谢岳龙、李哲豪、孙黄贤、古淑慧、叶韦成、林思婷、余玫仪、胡佳倩、锺宏源、黄伟嘉、任禹洁、李真苡、黄雅新、陈佳莹、吕伟诚、姚佳燕、徐郁婷、陈钲锠、吴佳颖、简婉如、王建棠、锺孟洁、陈品柔、纪婷文、胡存智、邱玉芸、锺雨庭、陈颀惠、黄蓝、林贝珊、余柏颉
  • 三立工程部
  • 工程统筹:龚美富
  • 星光导播:锺宜莹
  • 现场指导:李建霖、江国玮
  • 助理导播:张成柔、王薏宁
  • 技术指导:陈建良
  • 视讯工程师:刘世裕、吴元申、赵德昇
  • 视讯助理:张元威、王通燊
  • 摄影师:朱华阳、林明雄、王文龙、王新智、黄春镇、陈俊雄、林文陞
  • 灯光师:薛芳铭、王文枫、林中强、邱汉忠、李智伟、王孟蓁
  • 成音师:孟兆欣、叶志忠、夏永柠、罗梵笠、蔡豊泽、陈文隆
  • 后制统筹:苏玠玺
  • 剪辑指导:薛宇琳、许佳雯
  • 后制剪辑:范志明、吴鸿伟、赖庆原、黄珮瑜、李幸蓉、陈美绍、史昇鑫、张君豪
  • 影片制作:郑亨泰、古淑慧、巫少强、廖昱凯、杨治娟、黄雅新、吴佳颖、黄建国、林思婷、简婉如、李晨瑜
  • 影片音效:声都传播有限公司
  • 影片旁白:马克(沈子煜)
  • 影片灯光:邱汉光
  • 影片摄影:外景摄影组
  • 星光大道主持人:李霈瑜
    • 化妆:Backstage Jimy Wu
    • 发型:ZOOMhairstyling Spud_Tan 谭信文
    • 服装提供:APUJAN
    • 珠宝提供:APM monaco YUN YUN SUN
    • 造型:金比白工作室 Claire 化妆
  • 星光大道主持人:黄豪平
    • 化妆/发型:Ryan
    • 服装:沈子宸
  • 109 年度电视金钟奖颁奖典礼
  • 总监制:王淑娟
  • 执行监制:黄晓玫
  • 制作人:谢孟芬
  • 典礼制作群:王梦黛、邱湘莹、张伶卉、周矩源、林君谕、林孟如、吴亚桦、杨雅斐、王韵慈、杨治娟、陈钲锠、胡馥纯、吴佳颖、简婉如、王建棠、锺孟洁、陈奕颖、蔡妏雪、黄佳雯、周倢羽、黄至柔、邱亭瑄、许崇豪、苏子晴、蓝敬淇、李晨瑜、谢欣妤、林芳玉、锺欣惠、苏圣棋、江政颖、洪辰嫣、锺衣雯、凃嘉文、周妍廷、陈诗涵、沈美仪、陈淑卿、董依𬭚、苏振邺、蔡婉婷、赖玉婷、陈怡静、洪维信、杨雁捷、张韶恩、梁永青、梁家豪、林雅婷、李东元、蔡青萦、叶为诚、程仁伟、陈钰雯、凌静宜、许芳瑜、林友三、曹美琳、范振轩、黄雅文、陈宥亘、黎莉、黄鹏瑞、蔡宗翰、郑宇彤、田惠敏、廖翊婷、曾译卉、叶子瑄、王怡钧、陈怡如、郭柏旸、徐弦纭、徐嘉妤、邱苡洁、田筱琪、周亮辰、陈信智、曾琴、李奇莹、邱筱婷、徐郁婷、邱泠、余品贤
  • 三立工程
  • 工程统筹:龚美富
  • 导播:吴美君
  • 现场指导:邱雅玲、李紫瑀、李建霖、江国玮
  • 助理导播:黄雅琳、翁逸玫、李孟洁、萧谊諠
  • 技术指导:陈建良
  • 视讯工程师:刘世裕、吴元申、赵德昇
  • 视讯助理:张元威、王通燊
  • 摄影师:潘铭义、陈俊谊、王书镇、陈光杰、黄兆春、豊世颖、吴思宸、林茂荣、杜彦翔、吴茂瑞、林岢霈
  • 灯光师:薛芳铭、王文枫、林中强、邱汉忠、李智伟、王孟蓁
  • 成音师:孟兆欣、叶志忠、夏永柠、罗梵笠、蔡豊泽、陈文隆
  • 主持人:白家绮
    • 梳化:王盈乔
    • 发型:罗南
    • 造型:小意思造型设计工作室 莉丝、怡如
    • 礼服:bob Jian Daniel Wong
    • 珠宝:SHEE’S FINE JEWELRY 侍好珠宝
    • 鞋:Rene Caovilla
  • 主持人:Gino(蔡东威)
    • 发型:好剪才
    • 梳化:濬绮工作室 邱绣育
    • 造型:小意思造型设计工作室 莉丝、怡如
    • 礼服:Boss
    • 珠宝:LONGINES 浪琴表
    • 鞋:LAIO 复古绅士装
  • 特别感谢:凤凰艺能股份有限公司、民间全民电视公司

未完待补…

参考资料

  1. ^ 金钟奖直播资讯看这里 戏剧类大乱斗 追思桥段感伤,中央社,2020 年 9 月 26 日
  2. ^ 金钟奖第 55 届 完整入围名单,中央社,2020 年 8 月 26 日

外部链接

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/about-the-55th-golden-bell-awards/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
目录
  1. 1. 过程
    1. 1.1. 广播
    2. 1.2. 电视
  2. 2. 广播类入围暨得奖名单
    1. 2.1. 节目奖
      1. 2.1.1. 流行音乐节目奖
      2. 2.1.2. 类型音乐节目奖
      3. 2.1.3. 教育文化节目奖
      4. 2.1.4. 儿童节目奖
      5. 2.1.5. 少年节目奖
      6. 2.1.6. 社会关怀节目奖
      7. 2.1.7. 艺术文化节目奖
      8. 2.1.8. 生活风格节目奖
      9. 2.1.9. 社区节目奖
      10. 2.1.10. 广播剧奖
      11. 2.1.11. 单元节目奖
    2. 2.2. 个人奖
      1. 2.2.1. 流行音乐节目主持人奖
      2. 2.2.2. 类型音乐节目主持人奖
      3. 2.2.3. 教育文化节目主持人奖
      4. 2.2.4. 儿童节目主持人奖
      5. 2.2.5. 少年节目主持人奖
      6. 2.2.6. 社会关怀节目主持人奖
      7. 2.2.7. 艺术文化节目主持人奖
      8. 2.2.8. 生活风格节目主持人奖
      9. 2.2.9. 社区节目主持人奖
      10. 2.2.10. 企划编撰奖
      11. 2.2.11. 音效奖
    3. 2.3. 广告奖
      1. 2.3.1. 商品类广告奖
      2. 2.3.2. 非商品类广告奖
    4. 2.4. 电台奖
      1. 2.4.1. 电台品牌行销创新奖
      2. 2.4.2. 创新研发应用奖
    5. 2.5. 特别贡献奖
  3. 3. 电视类入围暨得奖名单
    1. 3.1. 节目奖
      1. 3.1.1. 戏剧节目奖
      2. 3.1.2. 迷你剧集奖
      3. 3.1.3. 电视电影奖
      4. 3.1.4. 自然科学纪实节目奖
      5. 3.1.5. 人文纪实节目奖
      6. 3.1.6. 儿童少年节目奖
      7. 3.1.7. 生活风格节目奖
      8. 3.1.8. 综艺节目奖
      9. 3.1.9. 益智及实境节目奖
      10. 3.1.10. 动画节目奖
    2. 3.2. 个人奖
      1. 3.2.1. 戏剧节目男主角奖
      2. 3.2.2. 戏剧节目女主角奖
      3. 3.2.3. 戏剧节目男配角奖
      4. 3.2.4. 戏剧节目女配角奖
      5. 3.2.5. 戏剧节目最具潜力新人奖
      6. 3.2.6. 迷你剧集/电视电影男主角奖
      7. 3.2.7. 迷你剧集/电视电影女主角奖
      8. 3.2.8. 迷你剧集/电视电影男配角奖
      9. 3.2.9. 迷你剧集/电视电影女配角奖
      10. 3.2.10. 迷你剧集/电视电影最具潜力新人奖
      11. 3.2.11. 戏剧节目导演奖
      12. 3.2.12. 迷你剧集/电视电影导演奖
      13. 3.2.13. 戏剧节目编剧奖
      14. 3.2.14. 迷你剧集/电视电影编剧奖
      15. 3.2.15. 自然科学及人文纪实节目主持人奖
      16. 3.2.16. 儿童少年节目主持人奖
      17. 3.2.17. 生活风格节目主持人奖
      18. 3.2.18. 综艺节目主持人奖
      19. 3.2.19. 益智及实境节目主持人奖
    3. 3.3. 技术类奖项
      1. 3.3.1. 非戏剧类节目导演奖
      2. 3.3.2. 非戏剧类节目导播奖
      3. 3.3.3. 戏剧类节目摄影奖
      4. 3.3.4. 非戏剧类节目摄影奖
      5. 3.3.5. 戏剧类节目剪辑奖
      6. 3.3.6. 非戏剧类节目剪辑奖
      7. 3.3.7. 声音设计奖
      8. 3.3.8. 灯光奖
      9. 3.3.9. 美术设计奖
    4. 3.4. 节目创新奖
    5. 3.5. 特别奖
      1. 3.5.1. 终身贡献奖
    6. 3.6. 追思逝世电视人
  4. 4. 表演节目
    1. 4.1. 广播金钟
    2. 4.2. 电视金钟
  5. 5. 评审名单
    1. 5.1. 广播金钟奖评审名单
    2. 5.2. 电视金钟奖评审名单
  6. 6. 金钟奖制作团队
    1. 6.1. 广播金钟
    2. 6.2. 电视金钟
  7. 7. 参考资料
  8. 8. 外部链接

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
\ No newline at end of file diff --git a/posts/add-email-subscription-to-your-hexo-blog/index.html b/posts/add-email-subscription-to-your-hexo-blog/index.html new file mode 100644 index 000000000..d38f55732 --- /dev/null +++ b/posts/add-email-subscription-to-your-hexo-blog/index.html @@ -0,0 +1,19 @@ +为你的 Hexo 博客添加邮件订阅 | CC的部落格

为你的 Hexo 博客添加邮件订阅

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

为你的 Hexo 博客添加邮件订阅你可能为你的 Hexo 博客配置了 RSS 订阅,但为什么不真正的利用它免费为你的博客添加邮件订阅呢?之前有讲过浏览器订阅,但只能本机订阅,并且数据清除了就相当于取消订阅,邮件订阅的自定义程度也蛮高的,所以个人也是极力推荐的

使用 mailchimp

你可能对它不是很熟悉,但或许见过这个 logo,Mailchimp 是通过电子邮件订阅 RSS 的在线工具

邮件推广是非常重要的营销方法之一。今天给各位做外贸电商的同学介绍一个免费的电子邮件发送工具:MailChimp,大家可以好好利用一下。MailChimp 的注册用户每月可以免费发送 10000 封邮件,收件人达 2000 人,这对于很多中小型电商来说,应该是足够用的。当然,如果你的会员数和月发信量超过了上面的标准,就需要付费了。

MailChimp,名字翻译过来就是邮件猩猩。最初 MailChimp 只是一家小型项目公司,为客户制作网站,有几个客户需要使用 email 发送器,所以他们就开发了一套 email 发送器给客户使用。当时 MailChimp 创造者们的想法是,这些客户都不太会操作电脑,为了避免麻烦,所以一定要做得非常简单,所以他们就将这套发送器昵称为“MailChimp”,意思是说,这套发送器,简单到连猩猩都会用。

也许有人听过这个网站,如果你有一些电子邮件想要大量寄给客户,可以自行购买或开发自己的邮件群发器,或者也可以上传到 MailChimp 的主机,由他们来帮你发送,顺便计算开信率、点击率……等等数字。MailChimp 发展了 10 年,今天已经是非常知名的发信工具,连TED(该公司每年举行的 TED 大会非常著名)、Magento经济学人等知名组织或公司都使用它,总共会员数高达 83 万,每个月必须平均寄出 17.5 亿封 email 出去。

下面就跟着我来慢慢实现这些功能吧

安装插件

我们首先需要生成文章 RSS 文件,然后提供给读者订阅阅读,如果你已经配置过了,可以跳过此步骤

按照官方进行配置即可

$ npm install hexo-generator-feed --save

然后在博客配置文件_config.yml中添加以下内容

feed:
enable: true
type: atom
path: atom.xml
limit: 20
hub:
content: false
content_limit: false
content_limit_delim: " "
order_by: -date
icon: icon.webp
autodiscovery: true
template:

更多配置可参考官方说明,但这里还是要说一下,我的博客目前是限制 1 篇,采用 rss 并选择全文输出,这样当我有更新时就可以将最新文章以 html 邮件的方式全文推送给订阅用户

到此当你执行hexo g命令时便会根据你的配置生成 RSS 文件

注册 mailchimp

mailchimp 官网在大陆访问并不慢,但某些域名(咱们可能用到的)访问就很慢,即使你关闭了谷歌人机验证选项,所以还是建议科学上网环境下操作

访问官网,自己按照要求注册就好了,不涉及注意事项,所以不再赘述,应该很简单就能注册吧,注册完毕后就进入控制台界面了

配置 mailchimp

这里直接放链接跳转了,不然又要写点击步骤太繁琐

  1. 点击这里根据我们的需要选择,我们这里选择的是分享博客更新(rss),或点击直达,当然有其他需求我们也可以自行配置,比如我就配置了欢迎新订阅者邮件,祝订阅者生日快乐邮件,反正一个月一万封邮件免费额度,又不会有很多人订阅,测试就都配置了

  1. 然后我们按照要求填写你的广告活动名称,选择受众 tag,

  1. 然后就开始根据你的需要自定义配置了,如果你的英语不是很好,建议选择带有翻译功能的浏览器,这里推送时间我们先按需要选择,然后待会儿去设置里更改时区即可,模板方面我们用免费的就够了,当然你也可以点击 Code Your Own 自己编辑代码或者上传导入模板,在设计界面拖动你想要的版块到需要的位置点击即可编辑

你可以通过发送测试邮件查看邮件查看效果或者待会儿配置完毕后预览(后面提到)

最后确定所有内容符合要求(绿色)没有警告即可确认完成配置Start RSS(最后一步警告的话,请根据提示自行解决,比较简单)

然后我们可以点击这里选择查看邮件最后预览效果

  1. 接下来我们配置一下用户订阅表格,我们主要用到的是第前两种(主要是 2 嵌入,但注意 官方 CSS 大陆无法访问,建议使用 JsDelivr 加速,js 可正常访问),当然后两种也可以配置,但是个人觉得没必要,不过你还是可以前往订阅页面查看一下效果

选择完毕后我们可以根据自己的需要编辑订阅页面然后完成所有步骤后保存即可,我们复制链接加入网站订阅页即可

  1. 但我们别忘了还有些时区没改呢,点击直达,根据自己的实际情况和喜好修改即可

到这里我们的配置基本结束了,其他细节配置请各位读者按照需要自行修改即可,这里不再赘述

测试邮件发送实际效果

关于邮件内容自定义程度很高,tag 关键词匹配等等,你可以根据个人喜好和需求去搭配使用,目前我设定好的模板预览如下

当然它关于邮件的变量不同的搭配可以实现最新文章,包含封面,最近文章,全文等等,其他搭配就根据你的需要决定啦

其他平台

你在订阅页也看到了,订阅界面一使用了其他平台,或者与 Tidio 等第三方进行了整合,下面简单介绍一下就好

Briefcake它的界面就很简洁,和上面的平台相比,如果你不是付费用户,选择我是创作者并配置好后

每天北京时间 8 点会给订阅者发送文章更新(如果有更新的话),并且是没有限制的,但功能比较简陋,页脚也不能自定义,但就提醒更新这个初衷来说是够用的,所以我也配置了,因为访问速度还不错啦

最后的最后,和之前介绍浏览器订阅一样,你还是得坚持内容产出,不要把它当作广告推销去使用而违背了初衷,因为我们只是博客,仅此而已,虽然现在阅读人数很少了,但哪天真的有人订阅了并且愿意等着你更新的话,也许值得曾经付出的默默码字的时光吧

弹窗订阅

虽然 Mailchimp 自带的弹窗订阅还 OK, 但我通常喜欢缝合,多功能合一才是王道,这个将在另一篇文章中说明 你以为 AddThis 只是个分享工具吗?

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/add-email-subscription-to-your-hexo-blog/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/awesome-status-pages/index.html b/posts/awesome-status-pages/index.html new file mode 100644 index 000000000..687797e69 --- /dev/null +++ b/posts/awesome-status-pages/index.html @@ -0,0 +1,19 @@ +很棒的状态页面 | CC的部落格

很棒的状态页面

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

本文首发在语雀 自动同步更新至CC 的部落格

Awesome status pages

Awesome list of status pages open source software, online services and public status pages of major internet companies

Opensource

  • Cachet - Laravel based status page system for everyone.
  • ClearStatus - Hugo-based status page, supports Netlify. Supports events from Github, Gitlab or any git repo with markdown.
  • Corestats - turn GitHub issues into a status page
  • cState - Simple, dev friendly, and free to host (Netlify & GitHub Pages)
  • Gatus - Automated service health dashboard
  • Issue Status - Simple, modern and flexible status page
  • Kardio - Simple Health Status Tool with Rich UI for Services deployed on Kubernetes and other platforms.
  • LambStatus (Deprecated)
  • Monitoror - monitoring wallboard
  • Server-Status
  • StashBoard - Python, for Google App Engine (Deprecated)
  • Static status - Bash script to generate a static status page
  • Statping
  • Statusfy
  • StatusOK
  • statuspage - Simple self-hosted open source status page site written in Django (inspired by Cachet)
  • Staytus  (Deprecated)
  • health_check - Simple health check of Rails app for use with uptime checking sites like newrelic and pingdom
  • status-page - Mountable status page for your Rails application, to check Cache, Redis, Sidekiq
  • health-monitor-rails - A Rails plugin which provides a health checking and monitoring API of various services and application aspects
  • Vigil - Microservices Status Page. Monitors a distributed infrastructure and sends alerts (Slack, SMS, etc.).
  • Statusimo - A PowerShell module that is able to generate a status page entirely from PowerShell.
  • Workers Status Page - Cloudflare Workers (completely on the edge) powered monitoring & status page.
  • Upptime - monitor and status page powered by GitHub
  • Uptimon - A PHP powered status page/monitoring solution.
  • Tinystatus - A tiny static status page generator (written in pure shell)

Services

Public status pages

目前使用

Instatus(中文)| Statuspage(English) 因为 Instatus 我贡献了翻译,而且相较于其他免费产品,可自定义的地方实在太多了(好评,白嫖党的胜利)而 Statuspage 主要是他可链接的第三方实在太多了,免费帐户的话能添加 25 个组件,反正也没有外国人看我,就当自用吧配合 Freshping, Uptimerobot 等监控联动,这两个均可自动化向推特发送通知,当然 Uptimerobot 自身推送的方式也很多,RSS, Telegram, Webhook 等满足日常需要了。此外良心的他们对于订阅更新支持也很完善,虽然根本没人会去订阅,但还是要有这些功能对吧,高大上点(不是)不过对于使用中文为主的我们来说,Instatus 是您的不二选择,时区,时间格式,语言什么的自定义太友好了,免费账号是完全够个人站长使用的,但是他的 embed 目前来说我希望能自适应大小,深色模式等,反正还很期待啦。而说到 embed, Statuspage 的 embed 个人觉得好看点吧,可以选择弹窗模式,悬浮模式,基础模式,徽标模式,自适应也不错,不过因为不支持中文(就是懒得自己在再整,官方那个代码都两年没动了)。此外 Instatus OUT 提供了网页端或者客户端(状态栏)快捷监控第三方的服务,而未来 Instatus 还会带来哪些服务呢,让我们共同期待吧!


但自从 Vercel 事件 后,我们自己的状态页不受影响,IP 换到了中国专用 IP,但是 Instatus 官方还是原来的 A 记录 IP,导致中国大陆用户无法访问其状态页和官网,这对用户体验来说是没什么,但对于站长就麻烦点了,得使用代理才能更新事件。不过 API, 邮件, WebHook 等方式应该可以解决,但官网控制面板更加方便,然后和开发者沟通更换了 IP, 目前一切正常,并且提前拥有了多语言和深色模式的支持,未来也会有其他功能,静态网页访问就是快!!!

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/awesome-status-pages/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
\ No newline at end of file diff --git a/posts/ccs-work-diary-part1/index.html b/posts/ccs-work-diary-part1/index.html new file mode 100644 index 000000000..ce76766b0 --- /dev/null +++ b/posts/ccs-work-diary-part1/index.html @@ -0,0 +1,19 @@ +CC的社畜日记 Part1 | CC的部落格

CC的社畜日记 Part1

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

一个半月的实习期过去了,我的生活发生了怎样的改变呢?

本文首发在语雀 自动同步更新至CC 的部落格

大三的时候,我的大多数同学,都是提前规划,知道自己想要什么(说实话我挺羡慕的,即使是为了工资去学习编程,并且最后拿到了不错的 Offer 的同学我也是打心底里祝福),但我直到毕业还没考虑清楚到底是偏软件还是硬件,我们这专业真的是干啥啥不行吗(电子信息工程)?;其实我在大一的时候有做过职业生涯规划,但是到了大三,由于各种原因,我似乎没有准备考研的念头,至少曾经信誓旦旦的默念,考不上也要试试,后来连尝试的勇气也没了(后来才发现我们班也就十几个)。所以可能别人五月份提前批就准备了,又或者是准备考研,但是我到了九月份开学才偶尔去宣讲会,招聘会,跑面试。但那时候我也不知道自己到底在倔强什么,眼高手低还是真的想出省看看(没错,一二线大城市总是令人向往)。当时只由一个要求,工作地点不再武汉,原因吗其实自己也说不上来,以至于老师也会反问一句武汉到底哪里得罪我了?是啊,我到底在为何执着呢?现在我不用再挤着二号线,坐一个多小时过长江,但是播报内容却时常在脑海回想;以前没觉得热干面有啥特别,或者说没上大学之前我是不能接受的,但现在老是想念那个味道,好像再也吃不到正宗的老汉口热干面;武汉对我来说又意味着什么呢,还是说仅仅是我们湖北的省会而已。

就这样,我错过了最好的秋招黄金期,也有海投过一些感兴趣的行业(虽然有面试机会,但我还是希望尽量远程面试,不过如果在武汉的话我还是会去现场面试,毕竟可以顺便了解一下),说真的,关乎自己未来的事情真的要提前做好规划,不然许多时候一团糟。比如一开始我每家公司投的简历都是一样的,没有针对性的去做调整,这样我其实错失很多机会,而且那时候我并没有确定自己未来的发展方向,所以真的,看到觉得还不错的也没做深入研究就投了出去,这是非常不科学的。我有面试一家公司,上午是群面,下午是个面,说真的,我感觉我发挥的还不错,但是到最后一步我还是紧张了,专业本来也没有那么对口,其实他们要求并不高,但是我可能怕他问太多,就过于谦虚,还犯了(我不会,但我可以学这种错误),其实这种双向选择你还是要尽全力去争取一下的,手里多拿几个 Offer,最后把主动权掌握在自己手里。虽然那家公司福利还不错啦,办公环境也 OK,但是需要经常出差,而且我不喜欢他们官网的设计(个人觉得有点丑,反正人家也没看上你,你还在这边嫌弃人家)。其实也不亏,就当混个经验,下午接到消息加了群,晚上做了个测试(浪费了一小时),就收到了第二天现场面试邀请,然后我还和 HR 说实话,因为距离有点远(其实我心里想的是,不报销路费和餐补,爬),本来没想来的(危险发言),顺便标榜了一下,答应了要来面试还是得来(现在回想起来,我真是蠢钝如猪)。

慢慢的,春招也快结束了,我必须得做个决断,家里也没给太大的压力,月入多少什么的,只要能养活自己就行。然后就还是想着先去一个比较大的平台沉淀几年,这样出来应该也是值钱的(肤浅);然后了那时候也不知道怎么想的,就想着苏州那地方应该养人吧,所以把工作地点定在了苏州,然后(格局小了——这里是吴江,不是苏州,别打我,吴江区,苏州?江苏人也不这么认为吧)后来发现我只是个给老板干活的,来了几个月了,又因为疫情,也没出去玩过。

下面呢,介绍一下我的公司以及日常主要工作,你要说哪点吸引我,除了经营使命是“环保-节能-爱地球”外,还是因为我幻想中以及 HR 画的饼(也不算)周围同事都是一堆很优秀的硕士博士,来了之后才发现,都不是我们实验室的,以前的大佬都高薪跳槽了,并且老员工的离职让我很不安,我时常觉得我只能靠自己,但是吧至少训练机制还是很成熟的,每个月都有各种课程可以自行报名,即使有些我听不懂,对未来发展还是不错的,然后工作环境还算比较舒适的,也没什么勾心斗角,比较单纯。当然啦我也有看企查查,还有职友集,领英,之类的帮助我判断(然而买不起会员看不到什么太有用的信息,想的就是试用期不行就跑路呗)

啊,没错,他就是某集团下的子公司,所以当我有什么不会的时候,我就去请教台湾前辈,毕竟他们那边的人真的很厉害,啥都能做,经验丰富。啊你在想为什么不问自己实验室的人呢,这也就是我一直在思考的问题,他们老是和我强调,还是得靠自己,现在我终于明白了,实验室四个人(包括我),除了一个见的多点的,我真的不知道能指望主管帮我什么,因此我听了一个月的 Love Yourself。

其实这就是职场,别人没有义务去主动教你,所以你一定要主动去问,哪怕是很小的和简单基础的问题,也要厚着脸皮去问,不过要是遇到那种不愿意教你的还是自己识相点,好在这边的人培养的都还是愿意帮助你的氛围,有问必答的,所以我还是很感谢他们。

我觉得写到这里我得配点图片至少,好吧,下面说说新人交流会的事情。一般大家都会觉得这是很重要的场合,表现好的话上面老板就会记住你,对自己未来的发展是有好处的对吧,不过我没有很在意这件事。于是乎,没有要模板,随便写了几乎话,好啦 PPT 做完了,睡觉。到了正式报告的那天,我听着各位大佬报告着他们做过的项目,以及详尽的规划,我只想说一句,似乎从来没有人教过我这些,从第一天到现在他们做过的工作,以及未来几个月的安排,他们似乎总是井井有条,在我各种鼓掌之后,到我了。很好我的报告主题是 Love Yourself ,似乎在给他们浇冷水,突然变得消极起来,甚至说了一些我平常不可能会讲的话,可以看出,当下的氛围其实是很奇怪的,不过我还是顶着压力讲完了。显然主管肯定要被留下来谈话,他们肯定吓坏了,这孩子说什么呢?于是乎,在下午的时候我就被叫到“小黑屋”谈心,真不错,还好我都听不进去鸡汤,我一直觉得她格局小了,只听进去了,没有人教你的,还是要靠自己,似乎与歌词相符。

So can you love yourself 你能爱自己吗 Love yourself 能好好爱自己吗 Ain’t nobody in this world gonna love you 如果你不爱自己 别人也不知怎么爱你 If you don’t love yourself 别人也不知怎么爱你 Save yourself 救赎要先靠自己 Save yourself 援兵就在前方 Ain’t nobody gonna save you 没有人能够给你救赎 If you don’t save yourself 除了你自己

她似乎想解开我的心结,一分耕耘一份收获,我提到的不接受排班,周末双休他说不可能的,问我有钱为什么不赚,让我觉得最好笑的是她说了句,他们都可喜欢加班了。我当时心想,如果不是有 Double,谁加班啊,谁喜欢,人资就是那么和我说的,按照我自己的工作安排,所以这一个月来我都是我想加班(安排的任务没处理完,重复无意义劳动)我才申请加班,拜托,天天加班累死好吗?

我只知道,我不算很优秀,但也因为我目前没什么压力,不过他们会给我压力,让我多赚钱,将来结婚买车买房… 但至少现阶段就是我看你不爽,我就是要 diao 你,你这个老板真的很不听话,所以有工作了十几年的员工都很不理解,可能他们需要的是稳定,也就只有我们才敢这样任性吧。

那么问题来了,因为疫情原因,人员流动性大(一直都不稳定,我只能说,18 年之后半导体实验室就没落了),于是乎入职前两天,本该几个星期的课程压缩到两天,左耳进右耳出,因为真的没意思;周四去实验室报道,熟悉了一下环境,周五看着师傅操作了一下,主管告诉我,下周我就要开始做案子了;一星期后我就能完成整个流程了,但是吧之后的几周里我开始做着这种简单重复的工作,我受够了;老板开始交给你任务,你刚毕业,对这个应该很熟吧,我这该死的工作效率,虽然他说我不需要懂(确实,我就是个没有感情的文档修订排版机器),白天干活,晚上修订,干完了这些,他来了绝,要不我们推翻 V1,V2 重新编排吧,只是复制粘贴,过两天就要上交了,这两天辛苦你了。很好我依旧是抽空修订,提前完工,给了一份让那边批注,修订,但几个星期过去了,还是没有任何消息,我只能说真的很急吗?

我的直属主管呢在我看来真的就是“舔狗”,老板啥都对,但他毕竟是个 TW 人,言语间还是露出蛛丝马迹,部门聚会我怎么可能去呢,你这个 TD🐕,让我坐你车,陪你吃饭,给你敬酒,爬!!!于是乎肠胃不舒服搪塞过去,反正也没啥(而且我吃完饭坐在图书馆看书,就开始下大雨,只能说庆幸,我可不想被淋湿。

或许是对我有什么不满,他开始在周会上很认真的鸡蛋里挑骨头,不过这时候我就是您说啥都对,我下去再看看,真好用!反正他明天就忘了,不用给自己找不快。

但我不能再继续这样下去了,我的担忧来自于这些有经验的前辈走了,我还没学会什么,于是我主动问了句,你们做的深吗?之前又考虑到这些问题吗?我很诧异这么些年都是怎么过来的,但毕竟也能理解,踢皮球,反正做到这一步就没我的事了。但长期这样下去,我会堕落的,所以开始主动学习一些比较难的,尝试着了解后续,所以半导体这块至少仪器我终于全会了,接下来就是每个案例拿来积累经验的时刻,当然基础知识以及英语可不能落下,毕竟总归会遇到的吗;主管总说遇到了再去查,见多了就会了,但我不是很认同,多准备点是没错的,她就是怕我不干活吧,然后学习那些事情放在工作时间之外,嗯还真是适合当领导。

于是乎,这一个半月我确实进步许多,但不变的是到点就走,在我的算法里,你上午给休息时间 10 分钟,下午 10 分钟(根本没人休息吧),这样算下来其实我一天工作 8 小时 20 分钟,我还是抽空划水吧,我是来赚钱的,下班不积极,脑子有问题。有一说一,你不让带吃的,还想让我值班 3 小时,你也知道我饿啊。

当然呢,距离实习结束还有一个半月,在看看吧,人到齐了该排课了吧,后面是走是留再观望一下吧,如果你再耗我时间,那我可没闲心陪你玩下去了;说真的选择比努力真的更重要,我要是早点明白这个道理应该也不会每天想太多了吧。

哦对,作为第三方实验室,经过 ISO 体系,CNAS 认证也没什么嘛,重要的人才没了,我还在这干嘛呀,享受自己专研出来的喜悦与自豪,抱歉,人不为己,难道取悦你吗?当然是积累经验好跳槽,另外台企,真的懂得都懂。

想起来我连目录还没写呢,哦,这只是篇日记,要什么目录,难道不是想到啥写啥吗?不是,如果没有规划,那么可以不写的,但反正写了也没人看,记下来也没啥,将来再看自己这个时候的想法应该会很有趣吧。

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/ccs-work-diary-part1/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/ccs-work-diary-part2/index.html b/posts/ccs-work-diary-part2/index.html new file mode 100644 index 000000000..d40090677 --- /dev/null +++ b/posts/ccs-work-diary-part2/index.html @@ -0,0 +1,20 @@ +CC的社畜日记 Part2 | CC的部落格

CC的社畜日记 Part2

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

查看本文语雀版本【首发】,自动同步更新至CC 的部落格

一些流水账

转眼间我已经步入社会快 5 个月了,我还是不太明白这社会的规则。他们教导我这世界不是非黑即白的,要学会圆滑一点,仔细想来倒也没有错。我也不是说喝了什么心灵鸡汤,我不够虚伪,但我足够自私?而在这几个月了,我没有与家人联系,删掉了他们的微信,没有接听电话,回复短信,有时候,我不知道自己在逃避什么。即使我爸精神出轨,但至少对我还算真心的吧,虽然他总是希望生个女孩,又或者格外偏爱小叔家的小孩,但我这么大了还是会吃小孩的醋。虽然我知道他给我打电话大概是为了要给我快递衣服,又或者问一下近况,可是搜索一下公司地址对他们来说应该也是件难事吧。或许我真的要求的太多了,怎么这么自私,和他们的交流大概只有转账记录,以至于上大学后真的没什么话题可以聊了,在他们心中,大概是养了条白眼狼,又或者当没养过这个孩子。姨妈发短信给我,大概是想让我回去看看我妈手术的事情,毕竟我那自认为不想让我牵挂的母亲也就没打算让我知道,他们没有告知我什么,就像我也没有告知他们我早就做好了器官或遗体捐赠的准备。我会嫌弃她为什么会让他把录音删掉,是她太没用了,还是我以前没怎么教她,毕竟她对智能手机的操作逻辑还是顺不过来,其实这是作为子女的失责吧。我也没想过有一天我要远程教母亲用手机取证父亲的语音记录,而不是想着如何去当一个润滑剂去调解中和家庭关系。我的想法是要离赶紧离,反正都不想过了,但我似乎没考虑过为什么他们等我工作了才告诉我这些。就这样一个人还是正常生活,一点也不去关心父母 没点想念他们的念头,其实在我脑海里他们的印象已经很弱了,过年回不回家这个似乎又成了我一个阶段性难题。写在网上 人家都说家丑不可外扬,但我似乎从开没有问过他们的想法,也没给他解释的机会,因为从二年级就一个人住校的原因,我似乎早已经习惯了这种生活,虽然我知道我和他们相处的日子不多了,但我却没想着赶紧抓住机会多多陪伴他们,而是如何逃离那个所谓的家。我也知道将来他们走了以后我一个人的日子有多难过,但我似乎丧失了斗志,觉得自己就是个普通的人,注定将平凡的度过一生,受疫情的影响,我的目标似乎降为了健康活着就挺好。

没能力改变现状

说实话,我挺累的,要在同事面前装着像个没事儿人,当然这对我工作还是产生了一定的影响,那就是似乎从不那么看中薪资到追求高薪,我担心的无非是挣的钱不够看病的,如果真的一个人孤独终老,那必须还是要有足够的经济基础作为支撑。但对我本专业的工作来说,我一个普通应届生,即使现在离职估计也不会有什么公司愿意要;如果继续从事半导体可靠性验证,失效分析相关工作,那么我可能需要熬一些年头,实习期满的时候奇葩主管约了爱心驿站心理咨询师(套话工具人)做一个实习期满回访访谈,表示自己骑驴找马找工作,马上部门主管知道了。虽然前面铺陈了一堆你的学习能力和工作能力没什么好说的,但是我们觉得你社交有问题,emm 其实早就知道他们会随便给个理由搪塞我,当她说我们根据综合评定决定延长你的试用期,我就知道以后没好日子过了,毕竟那么多人我一个刺头,她终究要表示她是上级,有一些权利的时候,我无法反驳。不过她很奇怪的问我什么时候会走,以便帮我延长试用期,挺可笑的。当时就回答的事最晚十二月底,其实内心只有一个想法,好啊,根据劳动法规定以书面形式规定试用期,当时签考核表的时候我留了个心眼拍照了(我是储干,所以直属主管就需要设定考核项目,满分 105 分上面写着低于 70 分延长试用期一个月,我也想不明白我为什么得不了 70 分),那就一个月后再说。4 个月前一天(周五)下午,她来恭喜我说和老板商量了一下,看我最近表现不错,决定给我转正了,我就会打了一个字:哦。她问我是不是不在乎啊,我说对啊(内心想法其实是反正就是工资差 300 块,其他没差啦),大概是我效率太高,太拼命,她以为我想干完了赶紧走,一时半会儿又招不到人,所以才给我转正吧,我不想转正的原因就是离职 3 天就好了,试用期至少也得一个星期,我看老员工拖了一个月,新员工一般两周,其实也就还可以接受。就这样我从半导体实验室去了物性实验室,美其名曰,我想多学点知识了,但实际上是不想接触发烟硝酸,硫酸,盐酸,丙酮之类的管制化学药品了,毕竟公司也没那么好心每周给你发几瓶纯牛奶解读,慢性作用谁也说不好。当然去了物性那边自然也不会给我什么常规案件,都是大批量,重复性苦力劳动,耗费时间也学不到什么东西,我也不愿去加班看资料。毕竟像我这样一天磨个三十几个完全是不在话下(规定是每天 6 个),我不过是想尽可能提早干完然后靠写报告拖进度吗,而我真实进度咱也不可能给他汇报,毕竟他会让你快点,再快点,我不想给自己挖坑,我一个人在交期前完成就好了,没必要把自己累死。但我为什么想趁着天气还暖和的时候把切片磨完呢,因为从技术层面上来说,我已经能把切片磨的很平,且恰到好处。但实验室设备不可能是我一个人一直占用,所以我要趁着支援其他同事的人还没来就处理完这些切片,虽然我知道处理完之后又会来下一批。而且水很凉 一天下来整个人其实很难受的,护手霜的钱公司这么抠也是不可能给你补贴的(我们这么大集团,你不要给公司省钱,那你倒是给个温水,开个空调暖气啊,哦我们要环保节能爱地球)。虽然我的工资没有缺过(但保不齐哪一天发生在我身上),但是其他三个同事因为周六加班领导没有签核,没有转薪,并且没有要补偿的想法,他们选择了认栽,其实我是无法理解的,应得的我的东西我就应该享有,工资这最基本的都无法保障你别和我谈什么其他的补偿。毕竟咱们主管一如既往的抠,因为如果要填联络单,主管要被人资那边记警告(这个根本不算事啊),你下属的工资你得给人家保障到位吧,而且本来就是有你的责任啊。直属主管给出的解决办法看起来在做好人实际上很不要脸。周末加班不来,也算一天哈哈(其实人资会不认的,毕竟没有打卡记录),但是人家想挣钱呢双倍呀。也不知道怎么想的,不管你怎么放假,人家的钱没了就是没了。而且主管过两天就返台了,明年才会见到(甚至都离职了,所以估计他们这钱是不好说了)。其实让我最恶心的是直属主管为了加班时跟我说的那句话,你的工资都是人家产线拼出来的,我们的工作就是配合产线,照她这样说那我每天不干活了,等着发工资吧,似乎我没有付出劳动(小杠一下)。她还会吐槽我的穿衣风格,如果有卡通图案的裤子,哪怕是有点花他就觉得应该成熟一点,当时反驳的话是,那你给我买啊,又不是花的你的钱,衣服又不穿你身上,管好你儿子就行了,哪那么多话。当然还有其他例子只能说我的直属主管和主管格局真的很小,小肚鸡肠还爱打小报告。不过很奇怪的是,主管一走一切都变得简单多了,开会再也不用讲那么多废话(毕竟她每天视奸,没必要向她报告,大家都心知肚明的事就没必要周会分享什么了。不过好在公司允许外网登录邮件,该有的都有备份,证据都好好存着呢,如果哪天我也到了忍不下去的地步,咱反手就是一个举报+仲裁。虽然现在我也时常让她在那生闷气,晚上睡不好觉,但我还是有责任心的,自己出来工作还是要树立口碑的,但其他部门同事都觉得她情商低那真的是没法说了。如果你坐在办公区,那她肯定会时不时来一句好累啊,喜欢戴着耳机大声讲电话,生怕别人听不见,就像他们大声密谋一样,我坐在那只能当个聋子。然后说到计划表中提到的年终尾牙部分,为什么没有排出具体时间,因为在我看来这是属于不重要且不紧急的事件,加上各种原因,我那主管发邮件的时候也没有带上我,发给了其他两个新人(又是不成文的规定:新人整节目),大概是我之前和她说要走吧,又或者她知道她无法强迫我来做这些,毕竟我不高兴就会和她对着干(属于是情商低+故意的+不给自己留后路),不如花点时间出来练习打字、PPT 制作或者 Office 的学习,剩余价值可不能被压榨完了。 2021-49W 任务清单-看板 📆 每周非计划日程表


吐槽完,还是要反思一下自己有哪些错误,那些可以改进,以帮助我提高不可替代性和价值,其实屏蔽公司定期面试看看行情和外面的要求挺好的,能迅速帮你找到定位和目标。而有时候我觉得自己在瞎忙,忙了一周但是却没有产出的时候我发现似乎是时间分配以及主次问题,所以我开始使用语雀的数据表功能按照四象限法进行 To Do Task 分配,再具体细化拟定每周非计划日程表,分配我的空余时间,看看我能不能再优化一下任务顺序,提升效率。事实证明,按照重要紧急这个顺序排列真的很好用。然后关于扩充自己的问题,由于重新进行了时间分配,我的效率进一步提高,于是就留出了空余时间供我学习,这是一个好现象。但目前一个很严重的问题就是早睡早起习惯的养成,毕竟我还想着每天起来去操场运动一下,毕竟这个习惯养成了,等再老几岁新陈代谢减慢,是很有帮助的,所以关于自律自控这个问题我也开始强迫自己,毕竟咱天生也不是那种人。说到专业知识,这四个月除了做案子几乎就是做案子,我没有深入去研究我为什么需要去做分析,样品在送到我手上之前发生了什么,失效模式,案件背景,使用环境条件其实都是我要考虑的问题。如果要成为一名优秀的失效分析工程师,我还有很多地方亟待努力,毕竟从局部到正体这是一个能力的跃迁,需要长时间的经验积累,但我也不知道是否有机会熬到那一天。那么另一条路就是赶紧转行去做个人更感兴趣的互联网行业,但我是要做时代的弄潮儿 还是被浪潮拍在沙滩上,这我可能试一试才知道,但如果不开始行动那一切只能是空想。不过目前还是要让自己有一条退路,至少和本专业还算是相关。


其实工作后有一个明显的变化,我虽然没有往家里拿过钱也没再要过钱,但我确实是合理消费了,并且愿意付费享受更有服务了,毕竟都是我自己赚来的钱。但因为不好意思和家里联系,很多东西就直接换新,然后也没存下什么钱,这是后期需要注意的。


不过也是有积累到一些人脉,或者说收获了友情,啊能认识帅哥真是值得高兴的事情!因为实验室属于公共部门的原因,会接触到其他许多部门的同事,这一点算是让我一个新来的有很大的参与感,当然我把 Skype 设为离开状态后大半个月也不会有人理我,大概是以为我离职了(大雾),因为之前老是各种人来问你专业知识或者说是当个传声筒,转交给助理或者其他部门同事,似乎只有我有空,人又好说话,但是把我还是不喜欢被占用时间处理这些琐碎杂项。
+
文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/ccs-work-diary-part2/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论

扫一扫

快速打开移动端➤
扫一扫二维码 快速打开移动端

扫一扫

请我喝杯牛奶➤
扫一扫二维码 请我喝杯牛奶
\ No newline at end of file diff --git a/posts/ccs-work-diary-part3/index.html b/posts/ccs-work-diary-part3/index.html new file mode 100644 index 000000000..905d45022 --- /dev/null +++ b/posts/ccs-work-diary-part3/index.html @@ -0,0 +1,19 @@ +CC的社畜日记 Part3 | CC的部落格

CC的社畜日记 Part3

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

查看本文语雀版本【首发】,自动同步更新至CC 的部落格

好久不见,距离上次更新已经过去半年了呢,但我毕业参加工作也快满一年了呢。23 岁生日仍然还是自己一个人过,但还是和往年一样,献血,骑行,看电影,吃饭然后回家,结束无聊的一天。

似乎有时间坐在这里开始总结一下这半年的感受了,毕竟也步入了工作方面也算是步入了正轨。但问题是为了避免套模板,每次做封面过于浪费时间了,当然你也发现了,封面是 jpg,顶图是 png,平白消耗你流量的我是屑。

工作使我快乐,钱使我更快乐

失效分析工程师?

Failure Analysis Engineer 失效分析工程师 Job Description 职位描述:

  1. 对产品进行故障分析从而找到问题点及失效根源

Perform failure analysis to the cause of the failure and the root cause of the failure.

  1. 开发测试/实验平台,完成相关文件(包括线路图、图纸等)

Develop testing/experiment platforms and deliver documents including circuit drawings and other drawings

  1. 撰写失效分析报告

Deliver failure analysis report.

  1. 拜访客户,进行现场失效分析

Field failure analysis via customer site visit.

  1. 基于分析结果提供有效的纠正措施和解决方案

Provide solutions and corrective actions to problems found via failure analysis. 似乎忘了什么,我只是每天在实验室干苦力的“失效分析助理工程师”,虽然没有给是打下手这一说,但职位确实如此,但干一样的活罢了,毕竟咱初始经验值为 0。其实和网上说的差不多,但这部分会在后面提到,所以不在展开。

学会与阿姨姐姐们相处

那么几乎都是成家的姐姐们,叫我小孩。当然我也知道,我不可能永远是小孩,我做的一些事,他们也会用“还小”来帮我分担压力,似乎我没懂游戏规则。我从同事那听到的最多一句话就是“还小”,但我也庆幸“还小”,毕竟第一份工作,以后就没人惯着我的脾气,我也学会收起锋芒,为人处世低调一点,不要老是硬碰硬,给老板当头一棒,这似乎是一种妥协,但至少不会背后落人闲话。但即使这样,还是有一些可笑的绯闻,办公室恋情,如果有录音笔,我是不是可以告诽谤啊,名誉权确实受损,主管和我的瘫痪我从一脸懵逼到震惊,原来问题已经发展至此了。但这一切也快结束了,她人走了就不会有闲话了。可是怎么没人信我说了多少遍了,我要男人!!!

主动“提前”换部门,学习新知识

我的初始部门,也就是面试的部门是半导体失效分析实验室,毕竟专业对口吗。那么限于实验室目前条件,仍然使用的是化学开盖方法,当然许多其他实验室亦如此,所以需要接触化学品(包括浓硫酸,发烟硝酸,丙酮等易制毒/易制爆/易挥发有毒物质),以及 X-Ray 等辐射。后续为了应付公安部(内部)检查,SOP 的需要,后续购买了防毒面具,防护服/鞋等装备,但我总觉得接触这些不是很好,所以直到现在我还是保持每天纯牛奶不断,毕竟我相信可以解毒的。不到两个月,我便申请了转调部门,当然是内部先调动,它的兄弟部门,物性失效分析实验室。以主管的话来说,我的学习能力还是毋庸置疑的,以至于她都忘记没给我找师傅,是的,他们总是说,没有人有义务教我。但随之而来的就是半年以来的切片验证,大批量,无意义,不懂脑子,费力不讨好的活似乎都是我在干了,毕竟我又快又好。当然直属主管意识不到问题的严重性,那就是我的不满足与自我怀疑,好在部门主管还算是比较喜欢我,明白我的心思,让这几个月的日子好受了点,我也更加得心应手。

部门还是合二为一,换了个寂寞

SFA 和 PFA 似乎有着斩不断的联系,于是 2022 年初,新官上任三把火,咱们正式合并为 FA 部,不分你我,但直到目前也是貌合神离的样子,两边的各种习惯还需要一段时间磨合,包括服务器文件的整理合并。但好在我两边都待过,所以合并对我来说影响不大,并且我掌握的专业技能确实比其他人要多,毕竟大佬们离职后我只能靠自己摸索,当然,一切还算顺利。

薪资涨幅 OK,但仍归汉心切


毕业前有多想要逃离武汉,现在就有多想回到武汉,以及最近不是有部电影《人生大事》吗,真的就是电影院没人认识,所以可以卸下防备肆无忌惮地哭,灯亮后回归成年人的生活。即使是这次薪资调整相较于其他人还行,但照这个架势下去,也不是个长久之地。

疫情总是打破原有计划

如果无法离开,不如好好呆着

集团现有学习资源,多一条后路

面试,裸辞?再就业?不待业!

有没有恋爱的冲动?

习惯了一人,但确实需要人陪伴

想参加一场婚礼,开始攒钱

父母这关,似乎始终是个结

怀旧情结,大概是人类通病

考古,0713,再就业男团

我的青春,败给了湖南卫视

打破无趣,好好生活


至少要留下来过的痕迹,所以关于失效分析或许会整理成工作笔记吧

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/ccs-work-diary-part3/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/course-design/index.html b/posts/course-design/index.html new file mode 100644 index 000000000..20253cb2d --- /dev/null +++ b/posts/course-design/index.html @@ -0,0 +1,19 @@ +课程设计 | CC的部落格

课程设计

课程设计本文仅作测试使用,因为删掉了原来的 webpush 当时 id 只是 7 千,现在使用的网站一万多啦,仅仅是因为 webpushr 域名站点更换问题,做个测试

一、课程设计任务与要求

课程设计目的

  1. 全面学习信号处理类课程所学理论知识,巩固所学知识重点和难点,将理论和实践很好地结合起来;
  2. 提高综合运用所学知识独立分析和解决问题的能力;
  3. 熟练使用一种高级语言进行编程实现。

课程设计要求

  1. 使用 Matlab(或其它开发工具)编程实现课程设计的内容,课程设计报告打印。
  2. 滤波器设计题目尽量避免使用现成的工具箱函数。为便于分析与观察,设计中所有频谱显示中的模拟频率应以实际频率显示,数字频率应对 π 归一化。
  3. 课程设计报告要求:(1)课程设计报告第 8 周周四下午 2:00 交,过期不交,无成绩;(2)报告可以打印,按要求标注图表号;(3)互相抄袭,无成绩。

课程设计内容

  1. 课题名称:彩色图像的边缘检测与处理
  2. 课题内容:(1)读入一幅彩色图像(有自己的生活照片);(2)将彩色图像进行三原色分解,分解出 R、G、B 分量,并用图像显示出来;(3)将彩色图像灰度化,转化为灰度图像并显示;(4)将灰度图像用三种以上典型的边缘检测算子进行边缘检测,显示检测出的边缘。(5)图像的任意角度旋转、裁剪(1.多种尺寸;2.选择性裁剪出指定目标,如只留下自己肩以上的图像);(6)选做:美颜处理或其他特效处理。

二、设计原理

读取、写入和查询图像文件

从本质上说,图形文件格式图像并非以 MATLAB 矩阵的形式存储,甚至不必以矩阵的形式存储。大多数图形文件都以包含特定格式信息标签的标头开头,然后是能够以连续流方式读取的位图数据。因此,不能使用标准的 MATLAB I/O 命令 load 和 save 来读取和写入图形文件格式图像。调用专门的 MATLAB 函数从图形文件格式读取和写入图像数据:

  1. 要读取图形文件格式图像,请使用 imread
  2. 要写入图形文件格式图像,请使用 imwrite
  3. 要获取有关图形文件图像的性质信息,请使用 imfinfo

读取图形图像

imread 函数能够按照任意受支持的位深读取任意受支持的图形文件中的图像。所读取的大多数图像均为 8 位。将这些图像读入内存后,以 uint8 类的形式来存储这些图像。这一规则的主要例外是 MATLAB 支持 16 位数据的 PNG 和 TIFF 图像;如果您读取 16 位的 PNG 或 TIFF 图像,那么该图像以 uint16 类的形式保存。注意对于索引图像,imread 始终将颜色图读入 double 类的数组,即使图像数组本身可能属于 uint8 或 uint16 类,也如此。

显示位图图像

以下命令可将图像 ngc6543a.jpg 读入工作区变量 RGB,然后用 image 函数来显示该图像:

RGB = imread('ngc6543a.jpg');image(RGB)

您可以使用 imwrite 函数写入(保存)图像数据。以下语句

load clown % An image that is included with MATLAB
imwrite(X,map,'clown.bmp')

可用于创建包含 clown 图像的 BMP 文件

彩色图像灰度化

rgb2gray 是 matlab 内部一种处理图像的函数,通过消除图像色调和饱和度信息同时保留亮度实现将 RGB 图像或彩色图转换为灰度图像,即灰度化处理的功能,调用这个功能的格式是 I = rgb2gray(RGB),意思是将真彩色图像 RGB 转换为灰度强度图像 I 。

调用格式说明

I = rgb2gray(RGB) 将真彩色RGB图像转换成灰度图像。(RGB并不发生变化)
newmap= rgb2gray(map) 返回一个灰度调色板。

函数算法

Matlab 中默认采用的是对 R、G、B 分量进行简单加法的公式:0.30R+ 0.59G + 0.11B

但是,这个方法对于 Gamma 校正的图片(平常所见到的 24 位真彩色图片均为 Gamma 校正的图片)并不适用,因为 Gamma 校正后的分量值不是物理上的功率,不能直接相加,因此,提出一种改进的算法来纠正这一问题。注意这里的 2.2 次方和 2.2 次方根,RGB 颜色值不能简单直接相加,而是必须用 2.2 次方换算成物理光功率。因为 RGB 值与功率并非简单的线性关系,而是幂函数关系,这个函数的指数称为 Gamma 值,一般为 2.2,而这个换算过程,称为 Gamma 校正。(注意,rgb2ntsc 函数也使用相同的权重来计算 Y 分量)

程序示例

% 1. 显示RGB真彩色图像
imgrgb = imread('flower.jpg');%用imread函数将图像读入,并且赋给变量imgrab
figure('Name', '显示真彩色图像')%开一个标题为“显示真彩色图像”的窗口
imshow(imgrgb)%显示真彩色图像imgrab
% 2. 显示灰度图像
imggray = rgb2gray(imgrgb);%调用rab2gray函数,将图像灰度化,赋给一个新的变量imggray
figure('Name', '显示灰度图像')%开一个标题为“显示灰度图像”的窗口
imshow(imggray)%显示图像灰度图imggray

图像边缘检测

图像最重要的特征之一就是边缘,它图像分割的主要依据。本次试验学习和了解边缘的基本特征、经典边缘检测算子(包括 Prewitt 算子,Roberts 算子, LoG 算子, Canny 算子)

1.Prewitt 算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。

2.Roberts 算子是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子,他采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高。

3.LoG 算子一种利用图像强度二阶导数的零交叉点来求边缘点的算法

4.Canny 算法使用 4 个 mask 检测水平、垂直以及对角线方向的边缘。原始图像与每个 mask 所作的卷积都存储起来。对于每个点都标识在这个点上的最大值以及生成的边缘的方向。这样就从可以原始图像生成了图像中每个点亮度梯度图以及亮度梯度的方向。较高的亮度梯度比较有可能是边缘,但是没有一个确切的值来限定多大的亮度梯度是边缘多大又不是,所以 Canny 使用了滞后阈值。

图像旋转

imrotate 是 matlab 中对图像进行旋转的操作命令

调用格式说明

B = imrotate(A,angle)

将图像 A(图像的数据矩阵)绕图像的中心点旋转 angle 度, 正数表示逆时针旋转, 负数表示顺时针旋转。返回旋转后的图像矩阵。

B = imrotate(A,angle,method)

使用 method 参数可以改变插值算法,method 参数可以为下面这三个值:

‘nearest’:最邻近插值(Nearest-neighbor interpolation)

‘bilinear’: 双线性插值(Bilinear interpolation)

‘bicubic’: 双三次插值(或叫做双立方插值)(Bicubic interpolation)

B = imrotate(A,angle,method,bbox)

bbox 参数用于指定输出图像属性:

‘crop’: 通过对旋转后的图像 B 进行裁剪, 保持旋转后输出图像 B 的尺寸和输入图像 A 的尺寸一样。

‘loose’: 使输出图像足够大, 以保证源图像旋转后超出图像尺寸范围的像素值没有丢失。 一般这种格式产生的图像的尺寸都要大于源图像的尺寸。

图像裁剪

imcrop 是一个函数,在 MATLAB 中,该函数用于返回图像的一个裁剪区域。可把图像显示在一个图像窗口中, 并允许用户以交互方式使用鼠标选定要剪切的区域。

调用格式:

I2 = imcrop(I)
X2 = imcrop(X,map)
RGB2 = imcrop(RGB)

这三种调用格式把图像显示在一个图像窗口中, 并允许用户以交互方式使用鼠标选定要剪切的区域。

I2 = imcrop(I,rect)
X2 = imcrop(X,map,rect)
RGB2 = imcrop(RGB,rect)

这三种格式都指定了要裁剪的矩形区域。

[...] = imcrop(x,y,...)
[A,rect] = imcrop(...)
[x,y,A,rect] = imcrop(...)

美颜效果

在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。

什么是图像滤波?

由于成像系统、传输介质和记录设备等的不完善,数字图像在其形成、传输记录过程中往往会受到多种噪声的污染。另外,在图像处理的某些环节当输入的像对象并不如预想时也会在结果图像中引入噪声。这些噪声在图像上常表现为一引起较强视觉效果的孤立像素点或像素块。一般,噪声信号与要研究的对象不相关它以无用的信息形式出现,扰乱图像的可观测信息。对于数字图像信号,噪声表为或大或小的极值,这些极值通过加减作用于图像像素的真实灰度值上,对图像造成亮、暗点干扰,极大降低了图像质量,影响图像复原、分割、特征提取、图像识别等后继工作的进行。要构造一种有效抑制噪声的滤波器必须考虑两个基本问题:能有效地去除目标和背景中的噪声;同时,能很好地保护图像目标的形状、大小及特定的几何和拓扑结构特征。

非线性滤波器:一般说来,当信号频谱与噪声频谱混叠时或者当信号中含有非叠加性噪声时如由系统非线性引起的噪声或存在非高斯噪声等),传统的线性滤波技术,如傅立变换,在滤除噪声的同时,总会以某种方式模糊图像细节(如边缘等)进而导致像线性特征的定位精度及特征的可抽取性降低。而非线性滤波器是基于对输入信号的一种非线性映射关系,常可以把某一特定的噪声近似地映射为零而保留信号的要特征,因而其在一定程度上能克服线性滤波器的不足之处。

双边滤波(Bilateral filter)是一种非线性滤波方法(空间权值+相似权值)——空间权值:模糊去噪;相似权值:保护边缘。

双边滤波原理

双边滤波具有两个权重:空间权重与相似权重

1)空间权重:与像素位置有关,为像素之间的距离(欧式距离,空间度量),故可定义为全局变量放在循环外

2)相似权重:与像素值大小有关,为像素值之间的距离(辐射距离,相似性度量),根据像素值不同而不同,需要放在循环内

3)两者结合,得到基于空间距离

双边滤波实现:实际应用时,根据需要对积分采用离散形式表示,滤波半径根据需要自行设置,在进行滤波前,需将数据转换为浮点型等。

双边滤波器(Bilateral filter)为使图像平滑化的非线性滤波器,它除了使用像素之间几何上的靠近程度之外,还多考虑了像素之间的灰度差异, 使得双边滤波器能够有效的将图像上的噪声去除,同时保存图像上的边缘信息。双边滤波器的好处是可以做边缘保护(edge preserving),一般用高斯滤波、均值滤波等滤波器去降噪,会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波多了一个高斯方差 sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

空间距离:指的是邻域内某点与中心点的欧式距离。空间域高斯函数其数学形式为(这就是高斯滤波核):

其中(xi,yi)为邻域内某点位置,(xc,yc)为中心点的位置,sigma 为空间域标准差。

灰度距离:指的是邻域内某点灰度与中心点灰度的差的绝对值。值域高斯函数其数学形式为:

其中 gray(xi,yi)为邻域内某点灰度值,gray(xc,yc)为中心点灰度值,sigma 为值域标准差。

对于高斯滤波,仅用空间距离的权值系数核与图像卷积后,确定中心点的灰度值。即认为离中心点越近的点,其权重系数越大。双边滤波中加入了对灰度信息的权重,即在邻域内,灰度值越接近中心点灰度值的点的权重更大,灰度值相差大的点权重越小。所以掩膜最终权重大小,则由空间域高斯核函数和值域高斯核函数共同确定。

σ 的意义及选取

1.空间域 sigma-d 选取:

sigma-d 越大,图像越平滑,趋于无穷大时,每个权重都一样,类似均值滤波;

sigma-d 越小,中心点权重越大,周围点权重越小,对图像的滤波作用越小,趋于零时,输出等同于原图。

2.值域 sigma-r 选取:

Sigma-r 越大,边缘越模糊,极限情况为 simga 无穷大,值域系数近似相等(忽略常数时,将近为 exp(0)= 1),与高斯模板(空间域模板)相乘后可认为等效于高斯滤波。

Sigma-r 越小,边缘越清晰,极限情况为 simga 无限接近 0,值域系数除了中心位置,其他近似为 0(接近 exp(-∞)=0),与高斯模板(空间域模板)相乘进行滤波的结果等效于原图像

三、程序设计

  1. 图像读取使用以下代码即可完成
[FileName, FilePath]=uigetfile('*.jpg;*.png;*.tif;*.img;*.gif;','请选择图像数据');
str=[FilePath FileName];i=imread(str);

这里借用数组存放着图片文件名和路径,同时限定了图片格式,用户也可手动选择其他格式

char - 字符数组,字符数组是一个字符序列,就像数值数组是一个数字序列一样。它的典型用途是将一小段文本作为一行字符存储在字符向量中。

但为了方便避免每次选择,测试过程中采取直接读取方式 i=imread(‘ME.jpg’);

  1. 使用通道提取 RGB 分量,事实上你看到的并不是只有单一的某种颜色,但是三者的确有者明显的差别

RGB 通道分量的提取后,再把分量串联起来作为一个对比结果也是正确的

cat - 串联数组。此 MATLAB 函数 沿维度 dim 将 B 串联到 A 的末尾。

我们需要合成的是三维(彩色)图像,所以以下可以实现

close all;clear;clc;
i= imread ('ME.jpg');
ir=i(:,:,1);ig=i(:,:,2);ib=i(:,:,3);
figure('numbertitle','off','name','图像三原色分解与合成');
subplot(1,2,1);imshow(i);title('原图');
X=cat(3,ir,ig,ib);subplot(122),imshow(X);title('合成真彩色图像');

当然合并方式不止上面那一种,比如

A(:,:,1)=r;A(:,:,2)=g;A(:,:,3)=b;image(A)

也是可以完成三通道合并。

至此,课程要求的内容已完成,但上面这种 RGB 通道分量的提取的效果,并不是我想要的结果。因此,我们使用图像的阈值分割。阈值分割的基本思想是确定一个阈值,然后把每个像素点的灰度值和阈 值相比较,根据比较的结果把该像素划分为两类——前景或背景。图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成为图像分割中最基本和应用最广泛的分割技术。它特别适用于目标和背景占据不同灰度级范围的图像。它不仅可以极大的压缩数据量,而且也大大简化了分析和处理步骤,因此在很多情况下,是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。图像阈值化的目的是要按照灰度级,对像素集合进行一个划分,得到的每个子集形成一个与现实景物相对应的区域,各个区域内部具有一致的属性,而相邻区域布局有这种一致属性。这样的划分可以通过从灰度级出发选取一个或多个阈值来实现。基本原理是:通过设定不同的特征阈值,把图像象素点分为若干类。常用的特征包括:直接来自原始图像的灰度或彩色特征;由原始灰度或彩色值变换得到的特征。

设置红、绿、蓝三种颜色提取阈值(越大越严格),具体效果不再占用篇幅演示

  1. 转化为灰度图像则直接调用 rgb2gray 函数即可
  2. 边缘检测,调用 edge 函数设定相应的参数即可,结果如下图
  3. 图像旋转,调用 imrotate 函数设定相应的参数即可,结果如下图
  4. 图像裁剪主要使用到的是 imcrop 函数,通过是否矩形裁剪区域大小来供用户手动裁剪或

自动裁剪,同时自动裁剪加上了红色裁剪区域边框以供用户对比查看,当然这得力于 Matlab 强大的交互查看功能

然后其实它能通过蒙版遮罩的方式达到抠图的效果,不过很简单,边缘细节处理的都不是很好,背景的话要不就是全黑要么你选择白色,下图是一个示例,

  1. 图像美颜,即用到了上面提到的双边滤波器,经测试后得到比较好的美颜效果图像如下

这张原照片仔细观察的话,其实脸上有各种痘痘,或者手抓后留下的痕迹,处理后胡子以及下巴上的痣也几乎看不出来了,皮肤更加光滑细腻,嘴唇颜色也红润了些许,但要想做到更好的话,我想大概需要优化皮肤美白效果,分别改变三个参数大小发现要不就是美颜效果不是很明显,要么就是过于朦胧,或过于虚化,像动漫里的人物,调试了许久后选择了当前参数,也符合之前查阅资料的的理论分析结果,以上生成结果图片都会自动保存在工作目录方便引用,这里不做复制粘贴

四、总结

遇到的问题和解决方法

  1. 关于从文件管理器读取文件,之前使用的时候记得,但太久没用了,不过有保存当时的代码,所以直接拿过来用了
  2. 图像手动裁剪操作,因为需要高速用户如何裁剪与得到裁剪结果,所以需要做一个 tips,但是使用 title 并没有成功显示,它有时候的确不是很好用,试过了 str、note 输出在命令行或者图片顶端,但因为字数过多不是很好看,最后选择 msgbox,并把窗口置顶,调整窗口位置和字体大小,未完成操作不允许执行下一步
  3. 美颜效果虽然方案多,但要想比较简单效果比较好的话还是很难的,毕竟 Matlab 不是 PS,或者说做个 GUI 界面出来,实现参数可调,但好的效果基本就在那一段,没什么可调的,所以用户选择图片后,就可以得到所有结果了

设计心得与体会

这次的课程设计时间虽然短暂,但我感觉收获颇多。之前接触 MATLAB 时对其在信号处理方面的兴趣就很感兴趣,自己利用课余时间也略有小研究,因此在图像处理的任务上,能够较轻松的完成。但由于自己对数字信号处理的理论知识理解不深,对数字滤波器的设计缺少知识,对于任务一研究了较长时间,设计过程中通过回顾滤波器设计的相关内容,再通过利用参考文献与网络,成功完成了任务。这次课程设计,让我加深了对之前抽象概念的理解,巩固了之前所了解的理论知识,并能很好的理解和掌握数字信号处理中的基本概念、基本原理、基本分析方法。同时掌握编程方法的技巧,与高级语言的程序设计相比,MATLAB 环境下可以更方便、快捷地进行设计,节省大量时间,且参数的修改也十分方便,还可以进一步进行优化设计。  这次的课程设计让我再次感受到 MATLAB 的强大功能,在今后的日子里,自己还需要不断的摸索。

五、参考文献

MATLAB 的 PDF 文档(来自 Mathworks 中文官网)

•   MATLAB 图形 (R2020a)

•   MATLAB 函数参考 (R2020a)

CSDN 博客

六、程序源代码清单

close all;clear;clc; %关闭图像显示窗口,清空工作区,清空命令行窗口
%要求(1)
[FileName, FilePath]=uigetfile('*.jpg;*.png;*.tif;*.img;*.gif;','请选择图像数据');str=[FilePath FileName];i=imread(str); %读入图像
figure('numbertitle','off','name','原始图像')%显示原始图像
imshow(i);title('原始图像');imwrite(i,'原始图像.jpg','jpg');
%要求(2)
ir=i(:,:,1);ig=i(:,:,2);ib=i(:,:,3);
figure('numbertitle','off','name','图像三原色分解')
subplot(2,2,1);imshow(i);title('原图');
subplot(2,2,2);imshow(ir);title('red 红色分量');imwrite(ir,'红色分量.jpg','jpg');%红色分量
subplot(2,2,3);imshow(ig);title('green 绿色分量');imwrite(ig,'绿色分量.jpg','jpg');%绿色分量
subplot(2,2,4);imshow(ib);title('blue 蓝色分量');imwrite(ib,'蓝色分量.jpg','jpg');%蓝色分量
%要求(3)
g=rgb2gray(i);%将图片转成灰度图片
figure('numbertitle','off','name','原始图像与其对应的灰度图像');
subplot(1,2,1),imshow(i);title(' 图一 原始图像');
subplot(1,2,2),imshow(g);title(' 图二 灰度图像');imwrite(g,'灰度图像.jpg','jpg');
%要求(4)
g=im2double(g); %转换为双精度,以便后面的计算
figure('numbertitle','off','name','边缘检测图像');
subplot(1,5,1),imshow(g),title('原图的灰度图');
PF=edge(g,'prewitt'); %边缘检测, Prewitt算子
subplot(1,5,2),imshow(PF),title('Prewitt算子');imwrite(PF,'Prewitt算子边缘检测.jpg','jpg');
RF=edge(g,'roberts');%边缘检测,Roberts算子
subplot(1,5,3),imshow(RF),title('Roberts算子');imwrite(RF,'Roberts算子边缘检测.jpg','jpg');
LF=edge(g,'log');%边缘检测,Log算子
subplot(1,5,4),imshow(LF),title('Log算子');imwrite(LF,'Log算子边缘检测.jpg','jpg');
CF=edge(g,'canny');%边缘检测,Canny算子
subplot(1,5,5),imshow(CF),title('Canny算子');imwrite(CF,'Canny算子边缘检测.jpg','jpg');
%要求(5)图像旋转部分
a1=imrotate(i,-30,'nearest','loose');
a2=imrotate(i,-45,'nearest','loose');
a3=imrotate(i,-60,'nearest','loose');
a4=imrotate(i,-90,'nearest','loose');
a5=imrotate(i,-135,'nearest','loose');
a6=imrotate(i,45,'nearest','loose');
a7=imrotate(i,135,'nearest','loose');
a8=imrotate(i,180,'nearest','loose');
figure('numbertitle','off','name','旋转任意角度的图像');%显示原始图像
subplot(3,3,5),imshow(i),title('未经旋转');
subplot(3,3,1),imshow(a1),title('顺时针旋转30°');imwrite(a1,'顺时针旋转30°.jpg','jpg');
subplot(3,3,2),imshow(a2),title('顺时针旋转45°');imwrite(a2,'顺时针旋转45°.jpg','jpg');
subplot(3,3,3),imshow(a3),title('顺时针旋转60°');imwrite(a3,'顺时针旋转60°.jpg','jpg');
subplot(3,3,4),imshow(a4),title('顺时针旋转90°');imwrite(a4,'顺时针旋转90°.jpg','jpg');
subplot(3,3,6),imshow(a5),title('顺时针旋转135°');imwrite(a5,'顺时针旋转135°.jpg','jpg');
subplot(3,3,7),imshow(a6),title('逆时针旋转45°');imwrite(a6,'逆时针旋转45°.jpg','jpg');
subplot(3,3,8),imshow(a7),title('逆时针旋转135°');imwrite(a7,'逆时针旋转135°.jpg','jpg');
subplot(3,3,9),imshow(a8),title('逆时针旋转180°');imwrite(a8,'逆时针旋转180°.jpg','jpg');
%要求(5)图像裁剪部分
rect=[75 68 130 112]; %定义剪切区域
I1=imcrop(i,rect); %进行图像剪切
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure('numbertitle','off','name','裁剪图像');
subplot(2,2,1),imshow(i),title('原始图像'); %显示原图像
rectangle('Position',rect,'LineWidth',2,'EdgeColor','r') %显示图像剪切区域
subplot(2,2,2),imshow(I1),title('自动剪切图像');imwrite(I1,'自动剪切图像.jpg','jpg'); %显示剪切的图像
%手动裁剪
subplot(2,2,3),imshow(i);
f = msgbox({'按住鼠标以选择初始裁剪区域','双击以确认','稍等一会儿即可查看裁剪结果'},'操作提示');
af = get( f, 'CurrentAxes' );
cf = get( af, 'Children' );
set( cf, 'FontSize', 12);
set(f,'WindowStyle','modal','Position',[300 300 200 100]);
%指定剪切区域的大小和位置,剪切,返回xy坐标和裁剪区域
[x,y,I2,rect]=imcrop(i);
subplot(2,2,4),imshow(I2),title('手动裁剪结果');imwrite(I2,'手动剪切图像.jpg','jpg');
%要求(6)美颜(双边滤波处理)
tempsize = 5;% 滤波半径
sigma1 = 5;% 全局方差
sigma2 = 0.08;% 局部方差
img = double(padarray(i,[tempsize,tempsize],0))/255;
%通道提取
imgr = img(:,:,1);imgg = img(:,:,2);imgb = img(:,:,3);[m,n] = size(imgr);%RGB
figure('numbertitle','off','name','双边滤波处理后的图像');%显示原始图像
subplot(1,2,1),imshow(i),title('原图');
%通道处理1
img(:,:,1) = B_filter(imgr,tempsize,sigma1,sigma2);
img(:,:,2) = B_filter(imgg,tempsize,sigma1,sigma2);
img(:,:,3) = B_filter(imgb,tempsize,sigma1,sigma2);
subplot(1,2,2),imshow(img(tempsize+1:m-tempsize,tempsize+1:n-tempsize,:))
title('双边滤波处理后图像')
imwrite(img(tempsize+1:m-tempsize,tempsize+1:n-tempsize,:),'美颜图像.jpg','jpg');
%双边滤波模板定义(放在最后)
function out = B_filter(Img,tempsize,sigma0,sigma1)
gauss = fspecial('gauss',2*tempsize+1,sigma0);
[m,n] = size(Img);
for i = 1+ tempsize : m - tempsize
for j = 1+ tempsize : n - tempsize
%提取处理区域得到梯度敏感矩阵
temp = abs(Img(i - tempsize:i + tempsize,j - tempsize:j + tempsize) - Img(i,j));
temp = exp(-temp.^2/(2*sigma1^2));
%得到双边滤波器并将权值和化为一
filter = gauss.*temp;
filter = filter/sum(filter(:));
%卷积
Img(i,j) = sum(sum((Img(i - tempsize:i + tempsize,j - tempsize:j + tempsize).*filter)));
end
end
out = Img;
end
文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/course-design/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/cusdis-or-disqus/index.html b/posts/cusdis-or-disqus/index.html new file mode 100644 index 000000000..bb23d7b2b --- /dev/null +++ b/posts/cusdis-or-disqus/index.html @@ -0,0 +1,19 @@ +Cusdis 还是 Disqus ? | CC的部落格

Cusdis 还是 Disqus ?

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

在中国大陆,如果追求用户的隐私保护,是否有更好的评论解决方案?

本文首发在语雀 自动同步更新至CC 的部落格

开源,免费,开箱即用,或零成本自托管,未来,有更多可能……

但目前的 Cusdis 它还不足以让我弃用不能在中国大陆访问的 Disqus

Cusdis

Open-source, lightweight (~5kb gzipped), privacy-friendly alternative to Disqus.

Features

  • Universal embed code
    • You can embed Cusdis on every website.
  • Light-weight sdk
    • The SDK that embed to your website is only 5kb (gzipped). Compared to Disqus (which is 24kb gzipped), it’s very light-weight.
  • Email notification
  • One-click import data from Disqus
  • Moderation dashboard
    • Since we don’t require user sign in to comment, all comments are NOT displayed by default, until the moderator approve it. We provide a moderation dashboard for it.

There are two ways to use Cusdis:

Self host

Pros: You own your data You can install Cusdis on your own server, just follow thisinstallation guide

Hosted service

Pros: Easy to use You can also use ourhosted service. We host our service onVercel, the data is stored on a PostgreSQL database.

Compared to Disqus

Cusdis is not designed for a FULLY alternative to Disqus, it’s aim to implement a minimist embed comment tool for small sites (like your static blog). Below are the pros and cons of Cusdis:

Pros

  • Cusdis is open-source and self-hostable, you own your data.
  • The SDK is lightweight (~5kb gzipped)
  • Cusdis doesn’t required commenter to sign in. We don’t use cookies at all.

Cons

  • Cusdis is on early development stage
  • You have to manually moderate comments which are not display by default until you approve it, since we dont’t have a spam filter.
  • Disqus is a company, we aren’t.

我的观点

观望中,适配起来也很简单,但目前不打算投入使用。好在由于很简约,语言也可以自定义,也做了深色模式适配,放在侧栏当做留言板给不能访问 Disqus 的游客使用,但有人肯定会问,是 Tidio 不能满足要求吗?还是其他评论看不上?

开头已经说了,我不想收集用户过多隐私信息,Tidio 和其他评论系统,都会记录下系统信息,IP 等不必要的敏感信息,对于静态博客来说,其实没必要。Disqus 虽然记录其实包括邮箱在内的信息全都***打码了,这也就是导出后的 Disqus 评论仅能作为一个备份,导入其他平台因为缺少邮箱这个信息头像无法显示的原因。Disqus 可以设定一个默认头像,当匿名评论者或者已注册的无头像用户评论时可以显示默认头像,并且它的 CDN 服务没有被墙,所以包括图片表情在内的都可正常显示,不用担心头像镜像的问题,只是 DisqusJS 没做这么多。而 Cusdis 目前没有头像显示这一功能,但后续应该会添加选项决定是否显示,导入 Disqus 评论后就可完美兼容,而又因为只有 5kb,不如 Disqus 那样臃肿,并且这个广告是让人无法忍受的,虽然我的博客因为流量太少官方瞧不起,不给我插广告躲过了,但万一哪天政策改了,免费用户强制广告,体验将极速降低,因为他不可控。再来我可以把数据掌握在自己手里,拥有一个够用的管理面板就够了。

虽然 Disqus 侧边栏管理评论很方便,并且可以通过邮件回复完成评论审核,但也因为这样,当你关闭评论审核,新评论通知就不发送了,所以我用上了 RSS 来获取评论通知。很开心 Cusdis 作者也很人性的将提供了同本博客 RSS 通过邮件订阅时,自动发送的确认邮件通知和取消订阅的选项。而对于博主收到的邮件提醒会附带一个按钮指向无需登陆批准回复的管理页面,电报等 Webhook 通知也如此。但这么一看目前好像全部都要审核很不方便,但该有的都会有的,处于快速迭代发展的它目前功能并不完善,但可以看出,它将是一个很好的评论系统。

Disqus 的匿名评论还有一点,就是需要谷歌真人验证 🤔,可以极大减少垃圾灌水评论,但本就无法访问服务的大陆用户真的会为了评论好不容易开了代理准备评论发现要点击图片验证,去注册一个账号?对于违禁词过滤似乎没考虑到中文这种分词,要求至少三个字所以不人性化,而长期缺少中文的训练或许反垃圾对于中文也很拉闸。

但作为博客灵活选择博客开启回应,页面关闭回应让游客反馈本篇文章如何却是我会在乎的。至于相关推荐还是使用使用自带的根据分类来吧,因为它抓取容易抓不到封面,而且并不是很智能。置顶,点赞,编辑评论,社交登陆等功能目前与这个输入信息一次性的评论来说显得格格不入,但不保证 Cusdis 未来会以小部件的方式供使用者自行选择,此外还期待一下可以和 Disqus 小部件一样人性化的最新评论功能,因为它简单的请求参数便可控制,是否显示头像,头像大小,评论条数,字数限制,以及是否显示管理员评论这些功能。

作者对包的体积似乎很执着,但平平淡淡才是真

DEMO

<div
id="cusdis_thread"
data-host="https://cusdis.ccknbc.cc"
data-app-id="blog"
data-page-id="/cusdis-or-disqus"
data-page-url="/cusdis-or-disqus"
data-page-title="Cusdis 还是 Disqus ?"
></div>
<script defer src="https://cusdis.ccknbc.cc/js/widget/lang/zh-cn.js"></script>
<script async defer src="https://cusdis.ccknbc.cc/js/cusdis.es.js"></script>

Widget

评论

<div id="wpac-comment"></div>
<script type="text/javascript">
wpac_init = window.wpac_init || [];
wpac_init.push({ widget: "Comment", id: 25905 });
(function () {
if ("WIDGETPACK_LOADED" in window) return;
WIDGETPACK_LOADED = true;
var mc = document.createElement("script");
mc.type = "text/javascript";
mc.async = true;
mc.src = "https://embed.widgetpack.com/widget.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mc, s.nextSibling);
})();
</script>
<a href="https://widgetpack.com" class="wpac-cr">Comments System WIDGET PACK</a>

点评

<div id="wpac-review"></div>
<script type="text/javascript">
wpac_init = window.wpac_init || [];
wpac_init.push({ widget: "Review", id: 25905 });
(function () {
if ("WIDGETPACK_LOADED" in window) return;
WIDGETPACK_LOADED = true;
var mc = document.createElement("script");
mc.type = "text/javascript";
mc.async = true;
mc.src = "https://embed.widgetpack.com/widget.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mc, s.nextSibling);
})();
</script>
<a href="https://widgetpack.com" class="wpac-cr">Reviews System WIDGET PACK</a>
文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/cusdis-or-disqus/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/digital-watermark-detection-based-on-wavelet-transform/index.html b/posts/digital-watermark-detection-based-on-wavelet-transform/index.html new file mode 100644 index 000000000..82d50f2f7 --- /dev/null +++ b/posts/digital-watermark-detection-based-on-wavelet-transform/index.html @@ -0,0 +1,19 @@ +基于小波变换的数字水印检测 | CC的部落格

基于小波变换的数字水印检测

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

基于小波变换的数字水印检测 数字水印技术原理

数字水印技术实际上就是通过对水印载体的分析、水印信息的处理、水印嵌入点的选择、嵌入方式的设计、嵌入调制的控制和提取检测方法等相关技术环节进行合理优化,寻求满足不可感知性、鲁棒性和安全性等约束条件下的准最优化设计问题。在实际应用中,一个完整水印系统的设计通常包括水印的生成、嵌入、检测和提取四个部分。

1   水印生成

通常基于伪随机数发生器或混沌系统来产生水印信号,从水印的鲁棒性和安全性方面来考虑,常常需要对原水印进行预处理来适应水印嵌入贺认。

2 水印嵌入

在尽量保证水印不可感知性的前提下,嵌入最大强度的水印,可提高水印的稳健性。常用的水印嵌入准则有加法准则、乘法准则和融合准则。

3 水印检测

指判断水印载体中是否存在水印的过程。

4 水印提取

指水印被比较精确地提取的过程。 水印的提取和检测可以需要原始图像的参与(明检测), 也可不需要原始图像的参与(盲检测)

数字水印的分类

  • 按水印的特性
  • 鲁棒数字水印:要求嵌入的水印能够经受各种常用的编辑处理
  • 脆弱数字水印:需要对信号的改动足够敏感,是人们能够根据脆弱水印的状态判断出数据是否被篡改。
  • 按水印的检测过程
  • 明文水印:检测工程中,需要原始数据。普遍来讲,鲁棒性较之盲水印要好。
  • 盲水印:只需要密钥,不需要原始数据
  • 按水印的内容
  • 有意义水印:水印是商标、音频片段等
  • 无意义水印:序列号,仅检测是否含水印
  • 按水印的隐藏位置
  • 空域
  • 频域
  • 时域

数字水印技术基本上具有下面几个方面的特点:

----安全性:数字水印的信息应是安全的,难以篡改或伪造,同时,应当有较低的误检测率,当原内容发生变化时,数字水印应当发生变化,从而可以检测原始数据的变更;当然数字水印同样对重复添加有很强的抵抗性

----隐蔽性:数字水印应是不可知觉的,而且应不影响被保护数据的正常使用;不会降质;

----鲁棒性:是指在经历多种无意或有意的信号处理过程后,数字水印仍能保持部分完整性并能被准确鉴别。可能的信号处理过程包括信道噪声、滤波、数/模与模/数转换、重采样、剪切、位移、尺度变化以及有损压缩编码等。

嵌入容量(embedding capacity):是指载体在不发生形变的前提下可嵌入的水印信息量。尤其是隐蔽通信领域的特殊性,对水印的容量需求很大。

图 1 数字水印嵌入与提取框图

典型的数字水印算法

数字水印的技术实现

空域-LSB

LSB 方法是最简单的嵌入水印的方法。事实上 ,任何一幅 图片都具备一定的容噪性 ,这表现在像素数据的最低有效位(Least Significant Bit,LSB)对 人 眼的视觉影响很 小,秘密信息就隐藏在图像每一个像素的最低位或次低位 ,实现其不 可见性。

频域

将图片的灰度强弱,视为图片的频域。通过某种变换手段(傅里叶变换,离散余弦变换,小波变换等)将图像变换到频域(小波域),在频域对图像添加水印,再通过逆变换,将图像转换为空间域。相对于空域手段,频域手段隐匿性更强,抗攻击性更高。

DCT

DCT 以 8x8 的像素为单位进行,生成的是 8x8 的 DCT 系数数据块。DCT 变换的最大特点是对于一般的图像都能够将像块的能量集中于少数低频 DCT 系数上,即生成 8x8DCT 系数块中,仅左上角的少量低频系数数值较大,其余系数的数值很小,这样就可能只编码和传输少数系数而不严重影响图像质量。

小波变换

“小波”就是小区域、长度有限、均值为 0 的波形。小波变换就是选择适当的基本小波或母小波 ψ(t),通过对基本小波的平移、伸缩而形成一系列的小波,这簇小波作为基可以构成一系列嵌套的(信号)子空间,然后将欲分析的信号(例如图像)投影到各个大小不同的(信号)子空间之中,以观察相应的特性。这样,就相当于我们用不同的焦距去观察一个物体,可从宏观到微观,从概貌到细节观察得十分详尽。所以小波变换又被称为“数学显微镜”。

空域+频域

该算法通过混沌置乱水印图像,建立水印与载体数据之间的 Hash 单向映射函数,使用两种不同的嵌入方法,先后嵌入水印到空域和 DFT 域。水印被多次嵌入,实现了水印的盲提取。

数字水印的应用场景

  • 多媒体作品盗版追溯:利用数字水印的不可见性,在不影响作品的情况下,加入版权信息的数字水印,可抗击拷贝,剪切。
  • 证件的防伪认证:如学历证,合同,票据等,携带数字水印后,可通过制定的方式提取水印,验证证件等数字文件是否被涂改;
  • 阿里事件:阿里追查泄密员工的时间本身,说明,水印可以有效的追溯信息的释放源;
  • 隐蔽信息传递:水印可携带加密信息后,藏在多媒体文件中传播,并通过特定的提取方式获取水印。可以作为一种隐蔽信息的通信方式。

源程序代码及部分注释

基础设置模块,同时存储着密钥,全局变量 main.m

global I ;
global W;
global P;
global Iw;
ntimes=23; % 秘钥1,Arnold置乱次数
rngseed=59433; % 秘钥2,随机数种子
flag=1; %是否显示图像,0 不显示,1 显示

嵌入水印模块:setdwtwatermark.m

matlabfunction [Iw,psnr]=setdwtwatermark(I,W,ntimes,rngseed,flag)
%基于小波变换数字水印嵌入
%I:载体图像,灰度图
%W:水印图像,二值图,且长宽相等
%ntimes: 秘钥1,Arnold置乱次数
I=imcrop(I,[0 0 size(I,2) size(I,1)-1]);
type=class(I);
I=double(I);
W=logical(W);
[mI,nI]=size(I);
[mW,nW]=size(W);
if mW~=nW
error('SETDWTWATERMARK:ARNOLD','ARNOLD置乱要求水印图像长宽必须相等!')
end
[ca1,ch1,cv1,cd1]=dwt2(I,'haar');
[ca2,ch2,cv2,cd2]=dwt2(ca1,'haar');
if flag
figure('Name','载体小波分解')
subplot(121)
imagesc([wcodemat(ca1),wcodemat(ch1);wcodemat(cv1),wcodemat(cd1)])
title('一级小波分解')
subplot(122)
imagesc([wcodemat(ca2),wcodemat(ch2);wcodemat(cv2),wcodemat(cd2)])
title('二级小波分解')
end
Wa=W;
H=[1,1;1,2]^ntimes;
for i=1:nW
for j=1:nW
idx=mod(H*[i-1;j-1],nW)+1;
Wa(idx(1),idx(2))=W(i,j);
end
end
flag=1;
if flag
figure('Name','水印置乱与嵌入')
subplot(221)
imshow(W)
title('原始水印')
subplot(222)
imshow(Wa)
title(['置乱水印,变换次数=',num2str(ntimes)]);
end
%数字水印嵌入
ca2w=ca2;
rng(rngseed);
idx=randperm(numel(ca2),numel(Wa));
for i=1:numel(Wa)
c=ca2(idx(i));
z=mod(c,nW);
if Wa(i)
if z<nW/4
f=c-nW/4-z;
else
f=c+nW*3/4-z;
end
else
if z<nW*3/4
f=c+nW/4-z;
else
f=c+nW*5/4-z;
end
end
ca2w(idx(i))=f;
end
ca1w=idwt2(ca2w,ch2,cv2,cd2,'haar');
Iw=idwt2(ca1w,ch1,cv1,cd1,'haar');
Iw=Iw(1:mI,1:nI);
mn=numel(I);
Imax=max(I(:));
psnr=10*log10(mn*Imax^2/sum((I(:)-Iw(:)).^2));
I=cast(I,type);
Iw=cast(Iw,type);
if flag
subplot(223)
imshow(I);
title('原始图像')
subplot(224);
imshow(Iw);
title(['添加水印,PSNR=',num2str(psnr)]);
end

提取水印模块:getdwtwatermark.m

function [Wg,nc]=getdwtwatermark(Iw,W,P,ntimes,rngseed,flag)
[mW,nW]=size(W);
if mW~=nW
error('GETDWTWATERMARK:ARNOLD','ARNOLD置乱要求水印图像长宽必须相等!')
end
Iw=double(Iw);
W=logical(W);
ca1w=dwt2(Iw,'haar');
ca2w=dwt2(ca1w,'haar');
Wa=W;
rng(rngseed);
idx=randperm(numel(ca2w),numel(Wa));
for i=1:numel(Wa)
c=ca2w(idx(i));
z=mod(c,nW);
if z<nW/2
Wa(i)=0;
else
Wa(i)=1;
end
end
Wg=Wa;
H=[2 -1;-1,1]^ntimes;
for i=1:nW
for j=1:nW
idx=mod(H*[i-1;j-1],nW)+1;
Wg(idx(1),idx(2))=Wa(i,j);
end
end
nc=sum(Wg(:).*W(:))/sqrt(sum(Wg(:).^2))/sqrt(sum(W(:).^2));
flag=1;
if flag
figure('Name','数字水印提取结果')
subplot(121)
W=imcrop(W,[0 0 size(P,2) size(P,1)]);
imshow(W)
title('原始水印')
subplot(122)
Wg=imcrop(Wg,[0 0 122 107]);
imshow(Wg)
title(['提取水印,NC=',num2str(nc)]);
end

GUI 调用模块 watermatk.m

function varargout = watermark(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @watermark_OpeningFcn, ...
'gui_OutputFcn', @watermark_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
function watermark_OpeningFcn(hObject, eventdata, handles, varargin)
movegui( hObject,'center' );
handles.output = hObject;%移动窗口到屏幕中心
guidata(hObject, handles);
function varargout = watermark_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
main
[filename pathname]=uigetfile({'*.jpg;*.bmp';'*.*'},'请选择底图文件');
%%打开图像
I=imread(filename); %读取原始图像
[filename pathname]=uigetfile({'*.png;*.tif';'*.*'},'请选择水印文件');
helpdlg('选择完毕,您可点击查看以确认是否需要重新选择','提示');
I = rgb2gray(I);%转换为灰度图
W = imread(filename);%读取水印图像
if strcmp(filename(end-3:end),'tif')
W= rgb2gray(W);
W=imbinarize(W);%转化成二值图像
end
P=W;
Mm=size(W,1); %水印的行数
Nm=size(W,2); %水印的列数
%将图像扩展为长宽相等
if Mm<Nm
Max=Nm;
Min=Mm;
for i=Min:Max
for j=1:Max
W(i,j)=1;
end
end
else
Max=Mm;
Min=Nm;
for i=1:Max
for j=Min:Max
W(i,j)=1;
end
end
end
function pushbutton2_Callback(hObject, eventdata, handles)
main
figure('Name','载体图像与水印图像')
subplot(211);
imshow(I);
title('载体图像')
subplot(212);
imshow(P);
title('水印图像')
function pushbutton3_Callback(hObject, eventdata, handles)
main
[Iw,psnr]=setdwtwatermark(I,W,ntimes,rngseed,0);
function pushbutton4_Callback(hObject, eventdata, handles)
main
[Wg,nc]=getdwtwatermark(Iw,W,P,ntimes,rngseed,0);

基于小波的水印技术 运行结果演示

1 图像的选择与导入

进入 GUI 主界面

图 2 GUI 主界面

点击选择图片,分别选择载体图像和水印图像

图 3 选择底图文件

图 4 选择水印文件

两项都选择完毕后提示选择完成,

图 5 选择完毕 帮助提示框

对于取消选择未设置警告与报错提示,防止过多弹窗

2 载体图像小波变换

这部分未单独新开按钮和图片显示窗口,但程序的确执行了,用户无需知晓

3 水印图像的预处理

图 6 预处理成二值图像后的水印

4 小波数字水印的嵌入

图 7 原始水印和置乱水印以及原始图像和添加水印之后的图像对比

5 小波数字水印的提取

图 8 原始水印和提取的水印的对比

将原始水印和提取水印进行对比,两个相关系数为 0.99356,相关系数越接近 1, 则提取的水印和原始水印越相似。

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/digital-watermark-detection-based-on-wavelet-transform/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
\ No newline at end of file diff --git a/posts/github-automatically-merges-pull-requests-notes/index.html b/posts/github-automatically-merges-pull-requests-notes/index.html new file mode 100644 index 000000000..4995ba385 --- /dev/null +++ b/posts/github-automatically-merges-pull-requests-notes/index.html @@ -0,0 +1,19 @@ +GitHub 自动合并 PR 笔记 | CC的部落格

GitHub 自动合并 PR 笔记

AI-摘要
切换
CC GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客

本文首发在语雀 自动同步更新至CC 的部落格

automerge-action

GitHub action to automatically merge pull requests when they are ready.

When added, this action will run the following tasks on pull requests with the automerge label:

  • Changes from the base branch will automatically be merged into the pull request (only when “Require branches to be up to date before merging” is enabled in the branch protection rules)
  • When the pull request is ready, it will automatically be merged. The action will only wait for status checks that are marked as required in the branch protection rules
  • Pull requests without any configured labels will be ignored

Labels, merge and update strategies are configurable, see Configuration.

A pull request is considered ready when:

  1. the required number of review approvals has been given (if enabled in the branch protection rules) and
  2. the required checks have passed (if enabled in the branch protection rules) and
  3. the pull request is up to date (if enabled in the branch protection rules)

After the pull request has been merged successfully, the branch will not be deleted. To delete branches after they are merged, see automatic deletion of branches.

Usage

Create a new .github/workflows/automerge.yml file:

name: automerge
on:
pull_request:
types:
- labeled
- unlabeled
- synchronize
- opened
- edited
- ready_for_review
- reopened
- unlocked
pull_request_review:
types:
- submitted
check_suite:
types:
- completed
status: {}
jobs:
automerge:
runs-on: ubuntu-latest
steps:
- name: automerge
uses: "pascalgn/automerge-action@v0.13.0"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

For the latest version, see the list of releases.

Configuration

The following merge options are supported:

  • MERGE_LABELS: The labels that need to be present for a pull request to be merged (using MERGE_METHOD). The default value is automerge. This option can be a comma-separated list of labels that will be checked. All labels in the list need to be present, otherwise the pull request will be skipped (until all labels are present). Labels prefixed with an exclamation mark (!) will block a pull request from being merged, when present. For example, when automerge,!wip,!work in progress is given, any pull requests with the labels wip or work in progress and any pull requests without the label automerge will not be merged. Blocking labels take precedence, so if a pull request has both labels wip and automerge, it will not be merged. When an empty string ("") is given, all pull requests will be merged.
  • MERGE_REMOVE_LABELS: The labels to automatically remove from a pull request once it has been merged by the action. The default value is "". This option can be a comma-separated list of labels that will be removed. When an empty string ("") is given, no labels will be removed.
  • MERGE_METHOD: Which method to use when merging the pull request into the base branch. Possible values are [merge](https://help.github.com/en/articles/about-pull-request-merges) (create a merge commit), [rebase](https://help.github.com/en/articles/about-pull-request-merges#rebase-and-merge-your-pull-request-commits) (rebase all commits of the branch onto the base branch) or [squash](https://help.github.com/en/articles/about-pull-request-merges#squash-and-merge-your-pull-request-commits) (squash all commits into a single commit). The default option is merge.
  • MERGE_METHOD_LABELS: Set to allow labels to determine the merge method (see MERGE_METHOD for possible values). For example, automerge=merge,autosquash=squash. If no such label is present, the method set by MERGE_METHOD will be used. The default value is "".
  • MERGE_METHOD_LABEL_REQUIRED: Set to true to require one of the MERGE_METHOD_LABELS to be set. The default value is false.
  • MERGE_COMMIT_MESSAGE: The commit message to use when merging the pull request into the base branch. Possible values are automatic (use GitHub’s default message), pull-request-title (use the pull request’s title), pull-request-description (use the pull request’s description), pull-request-title-and-description or a literal value with optional placeholders (for example Auto merge {pullRequest.number}). The default value is automatic.
  • MERGE_COMMIT_MESSAGE_REGEX: When using a commit message containing the PR’s body, use the first capturing subgroup from this regex as the commit message. Can be used to separate content that should go with the commit into the code base’s history from boilerplate associated with the PR (licensing notices, check lists, etc). For example, (.*)^--- would keep everything up until the first 3-dash line (horizontal rule in MarkDown) from the commit message. The default value is empty, which disables this feature.
  • MERGE_FILTER_AUTHOR: When set, only pull requests raised by this author will be merged automatically.
  • MERGE_FORKS: Whether merging from external repositories is enabled or not. By default, pull requests with branches from forked repositories will be merged the same way as pull requests with branches from the main repository. Set this option to false to disable merging of pull requests from forked repositories. The default value is true.
  • MERGE_RETRIES and MERGE_RETRY_SLEEP: Sometimes, the pull request check runs haven’t finished yet, so the action will retry the merge after some time. The number of retries can be set with MERGE_RETRIES. The default number of retries is 6 and setting it to 0 disables the retry logic. MERGE_RETRY_SLEEP sets the time to sleep between retries, in milliseconds. The default is 5000 (5 seconds) and setting it to 0 disables sleeping between retries.
  • MERGE_DELETE_BRANCH: Automatic deletion of branches does not work for all repositories. Set this option to true to automatically delete branches after they have been merged. The default value is false.

The following update options are supported:

  • UPDATE_LABELS: The labels that need to be present for a pull request to be updated (using UPDATE_METHOD). The default value is automerge. Note that updating will only happen when the option “Require branches to be up to date before merging” is enabled in the branch protection rules. This option can be a comma-separated list of labels, see the MERGE_LABELS option for more information.
  • UPDATE_METHOD: Which method to use when updating the pull request to the base branch. Possible values are merge (create a merge commit) or rebase (rebase the branch onto the head of the base branch). The default option is merge. When the option is rebase and the rebasing failed, the action will exit with error code 1. This will also be visible in the pull request page, with a message like “this branch has conflicts that must be resolved” and a list of conflicting files.
  • UPDATE_RETRIES and UPDATE_RETRY_SLEEP: Sometimes, the pull request check runs haven’t finished yet and the action doesn’t know if an update is necessary. To query the pull request state multiple times, the number of retries can be set with UPDATE_RETRIES. The default number of retries is 1 and setting it to 0 disables the retry logic. UPDATE_RETRY_SLEEP sets the time to sleep between retries, in milliseconds. The default is 5000 (5 seconds) and setting it to 0 disables sleeping between retries.

Also, the following general options are supported:

  • GITHUB_TOKEN: This should always be "${{ secrets.GITHUB_TOKEN }}". However, in some cases it can be useful to run this action as a certain user (by default, it will run as github-actions). This can be useful if you want to use the “Restrict who can push to matching branches” option in the branch protection rules, for example. To use this setting for manually providing a token, you need to create a personal access token for the user (make sure to check public_repo when it’s a public repository or repo when it’s a private repository). All API requests (merge/rebase) will then be executed as the specified user. The token should be kept secret, so make sure to add it as secret, not as environment variable, in the GitHub workflow file!

You can configure the environment variables in the workflow file like this:

env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
MERGE_LABELS: "automerge,!work in progress"
MERGE_REMOVE_LABELS: "automerge"
MERGE_METHOD: "squash"
MERGE_COMMIT_MESSAGE: "pull-request-description"
MERGE_FORKS: "false"
MERGE_RETRIES: "6"
MERGE_RETRY_SLEEP: "10000"
UPDATE_LABELS: ""
UPDATE_METHOD: "rebase"

Supported Events

Automerge can be configured to run for these events:

  • check_run
  • check_suite
  • issue_comment
  • pull_request_review
  • pull_request_target
  • pull_request
  • push
  • repository_dispatch
  • schedule
  • status
  • workflow_dispatch

For more information on when these occur, see the Github documentation on events that trigger workflows and their payloads.

Limitations

Debugging

To run the action with full debug logging, update your workflow file as follows:

- name: automerge
uses: pascalgn/automerge-action@...
with:
args: "--trace"

If you need to further debug the action, you can run it locally.

You will need a personal access token.

Then clone this repository, create a file .env in the repository, such as:

GITHUB_TOKEN="123abc..."
URL="https://github.com/pascalgn/repository-name/pull/123"

Install dependencies with yarn, and finally run yarn it (or npm run it).

License

MIT

bulldozer

bulldozer is a GitHub App that automatically merges pull requests (PRs) when (and only when) all required status checks are successful and required reviews are provided.

Additionally, bulldozer can:

  • Only merge pull requests that match certain conditions, like having a specific label or comment
  • Ignore pull requests that match certain conditions, like having a specific label or comment
  • Automatically keep pull request branches up-to-date by merging in the target branch
  • Wait for additional status checks that are not required by GitHub

Bulldozer might be useful if you:

  • Have CI builds that take longer than the normal review process. It will merge reviewed PRs as soon as the tests pass so you don’t have to watch the pull request or remember to merge it later.
  • Combine it with policy-bot to automatically merge certain types of pre-approved or automated changes.
  • Want to give contributors more control over when they can merge PRs without granting them write access to the repository.
  • Have a lot of active development that makes it difficult to merge a pull request while it is up-to-date with the target branch.

Contents

Behavior

bulldozer will only merge pull requests that GitHub allows non-admin collaborators to merge. This means that all branch protection settings, including required status checks and required reviews, are respected. It also means that you must enable branch protection to prevent bulldozer from immediately merging every pull request.

Only pull requests matching the trigger conditions (or not matching ignore conditions) are considered for merging. bulldozer is event-driven, which means it will usually merge a pull request within a few seconds of the pull request satisfying all preconditions.

Configuration

The behavior of the bot is configured by a .bulldozer.yml file at the root of the repository. The file name and location are configurable when running your own instance of the server.

The .bulldozer.yml file is read from the most recent commit on the target branch of each pull request. If bulldozer cannot find a configuration file, it will take no action. This means it is safe to enable the bulldozer on all repositories in an organization.

bulldozer.yml Specification

The .bulldozer.yml file supports the following keys.

# "version" is the configuration version, currently "1".
version: 1

# "merge" defines how and when pull requests are merged. If the section is
# missing, bulldozer will consider all pull requests and use default settings.
merge:
# "trigger" defines the set of pull requests considered by bulldozer. If
# the section is missing, bulldozer considers all pull requests not excluded
# by the ignore conditions.
trigger:
# Pull requests with any of these labels (case-insensitive) are added to
# the trigger.
labels: ["merge when ready"]

# Pull requests where the body or any comment contains any of these
# substrings are added to the trigger.
comment_substrings: ["==MERGE_WHEN_READY=="]

# Pull requests where any comment matches one of these exact strings are
# added to the trigger.
comments: ["Please merge this pull request!"]

# Pull requests where the body contains any of these substrings are added
# to the trigger.
pr_body_substrings: ["==MERGE_WHEN_READY=="]

# Pull requests targeting any of these branches are added to the trigger.
branches: ["develop"]

# Pull requests targeting branches matching any of these regular expressions are added to the trigger.
branch_patterns: ["feature/.*"]

# "ignore" defines the set of pull request ignored by bulldozer. If the
# section is missing, bulldozer considers all pull requests. It takes the
# same keys as the "trigger" section.
ignore:
labels: ["do not merge"]
comment_substrings: ["==DO_NOT_MERGE=="]

# "method" defines the merge method. The available options are "merge",
# "rebase", "squash", and "ff-only".
method: squash

# Allows the merge method that is used when auto-merging a PR to be different based on the
# target branch. The keys of the hash are the target branch name, and the values are the merge method that
# will be used for PRs targeting that branch. The valid values are the same as for the "method" key.
# Note: If the target branch does not match any of the specified keys, the "method" key is used instead.
branch_method:
develop: squash
master: merge

# "options" defines additional options for the individual merge methods.
options:
# "squash" options are only used when the merge method is "squash"
squash:
# "title" defines how the title of the commit message is created when
# generating a squash commit. The options are "pull_request_title",
# "first_commit_title", and "github_default_title". The default is
# "pull_request_title".
title: "pull_request_title"

# "body" defines how the body of the commit message is created when
# generating a squash commit. The options are "pull_request_body",
# "summarize_commits", and "empty_body". The default is "empty_body".
body: "empty_body"

# If "body" is "pull_request_body", then the commit message will be the
# part of the pull request body surrounded by "message_delimiter"
# strings. This is disabled (empty string) by default.
message_delimiter: ==COMMIT_MSG==

# "required_statuses" is a list of additional status contexts that must pass
# before bulldozer can merge a pull request. This is useful if you want to
# require extra testing for automated merges, but not for manual merges.
required_statuses:
- "ci/circleci: ete-tests"

# If true, bulldozer will delete branches after their pull requests merge.
delete_after_merge: true

# "update" defines how and when to update pull request branches. Unlike with
# merges, if this section is missing, bulldozer will not update any pull requests.
update:
# "trigger" defines the set of pull requests that should be updated by
# bulldozer. It accepts the same keys as the trigger in the "merge" block.
trigger:
labels: ["WIP", "Update Me"]

# "ignore" defines the set of pull requests that should not be updated by
# bulldozer. It accepts the same keys as the ignore in the "merge" block.
ignore:
labels: ["Do Not Update"]

FAQ

Can I specify both ignore and trigger?

Yes. If both ignore and trigger are specified, bulldozer will attempt to match on both. In cases where both match, ignore will take precedence.

Can I specify the body of the commit when using the squash strategy?

Yes. When the merge strategy is squash, you can set additional options under the options.squash property, including how to render the commit body.

merge:
method: squash
options:
squash:
body: summarize_commits # or `pull_request_body`, `empty_body`

You can also define part of pull request body to pick as a commit message when body is pull_request_body.

merge:
method: squash
options:
squash:
body: pull_request_body
message_delimiter: ==COMMIT_MSG==

Anything that’s contained between two ==COMMIT_MSG== strings will become the commit message instead of whole pull request body.

What if I don’t want to put config files into each repo?

You can add default repository configuration in your bulldozer config file.

It will be used only when your repo config file does not exist.

options:
default_repository_config:
ignore:
labels: ["do not merge"] # or any other available config.

Bulldozer isn’t merging my commit when it should, what could be happening?

Bulldozer will attempt to merge a branch whenever it passes the trigger/ignore criteria. GitHub may prevent it from merging a branch in certain conditions, some of which are to be expected, and others that may be caused by mis-configuring Bulldozer.

  • Required status checks have not passed
  • Review requirements are not satisfied
  • The merge strategy configured in .bulldozer.yml is not allowed by your repository settings
  • Branch protection rules are preventing bulldozer[bot] from pushing to the branch. Github apps can be added to the list of restricted push users, so you can allow Bulldozer specifically for your repo.

Bulldozer isn’t updating my branch when it should, what could be happening?

When using the branch update functionality, Bulldozer only acts when the target branch is updated after updates are enabled for the pull request. For example:

  1. User A opens a pull request targetting develop
  2. User B pushes a commit to develop
  3. User A adds the update me label to the first pull request
  4. User C pushes a commit to develop
  5. Bulldozer updates the pull request with the commits from Users B and C

Note that the update does not happen when the update me label is added, even though there is a new commit on develop that is not part of the pull request.

Can Bulldozer work with push restrictions on branches?

As mentioned above, as of Github ~2.19.x, GitHub Apps can be added to the list of users associated with push restrictions. If you don’t want to do this, or if you’re running an older version of Github that doesn’t support this behaviour, you may work around this:

  1. Use another app like policy-bot to implement approval restrictions as required status checks instead of using push restrictions. This effectively limits who can push to a branch by requiring changes to go through the pull request process and be approved.
  2. Configure Bulldozer to use a personal access token for a regular user to perform merges in this case. The token must have the repo scope and the user must be allowed to push to the branch. In the server configuration file, set:
options:
push_restriction_user_token: <token-value>
  1. The token is only used if the target branch has push restrictions enabled. All other merges are performed as the normal GitHub App user.

Deployment

bulldozer is easy to deploy in your own environment as it has no dependencies other than GitHub. It is also safe to run multiple instances of the server, making it a good fit for container schedulers like Nomad or Kubernetes.

We provide both a Docker container and a binary distribution of the server:

A sample configuration file is provided at config/bulldozer.example.yml. Certain values may also be set by environment variables; these are noted in the comments in the sample configuration file.

GitHub App Configuration

To configure Bulldozer as a GitHub App, these general options are required:

  • Webhook URL: http(s)://<your-bulldozer-domain>/api/github/hook
  • Webhook secret: A random string that matches the value of the github.app.webhook_secret property in the server configuration

The app requires these permissions:

PermissionAccessReason
Repository administrationRead-onlyDetermine required status checks
ChecksRead-onlyRead checks for ref
Repository contentsRead & writeRead configuration, perform merges
IssuesRead & writeRead comments, close linked issues
Repository metadataRead-onlyBasic repository data
Pull requestsRead & writeMerge and close pull requests
Commit statusRead-onlyEvaluate pull request status

The app should be subscribed to these events:

  • Check run
  • Commit comment
  • Pull request
  • Status
  • Push
  • Issue comment
  • Pull request review
  • Pull request review comment

Operations

bulldozer uses go-baseapp and go-githubapp, both of which emit standard metrics and structured log keys. Please see those projects for details.

Example Files

Example .bulldozer.yml files can be found in [config/examples](https://github.com/palantir/bulldozer/tree/develop/config/examples)

Migrating: Version 0.4.X to 1.X

The server configuration for bulldozer allows you to specify configuration_v0_path, which is a list of paths to check for 0.4.X style bulldozer configuration. When a 1.X style configuration file does not appear at the configured path, bulldozer will attempt to read from the paths configured by configuration_v0_path, converting the legacy configuration into an equivalent v1 configuration internally.

The upgrade process is therefore to deploy the latest version of bulldozer with both configuration_path and configuration_v0_path configured, and to enable the bulldozer GitHub App on all organizations where it was previously installed.

Development

To develop bulldozer, you will need a Go installation.

Run style checks and tests

./godelw verify

Running the server locally

# copy and edit the server config
cp config/bulldozer.example.yml config/bulldozer.yml

./godelw run bulldozer server
  • config/bulldozer.yml is used as the default configuration file
  • The server is available at http://localhost:8080/

Running the server via Docker

# copy and edit the server config
cp config/bulldozer.example.yml config/bulldozer.yml

# build the docker image
./godelw docker build --verbose

docker run --rm -v "$(pwd)/config:/secrets/" -p 8080:8080 palantirtechnologies/bulldozer:latest
  • This mounts the config directory (which should contain the bulldozer.yml configuration file) at the expected location
  • The server is available at http://localhost:8080/

Contributing

Contributions and issues are welcome. For new features or large contributions, we prefer discussing the proposed change on a GitHub issue prior to a PR.

License

This application is made available under the Apache 2.0 License.

probot-auto-merge

A GitHub App built with Probot that automatically merges PRs

Usage

  1. Configure the GitHub App
  2. Create .github/auto-merge.yml in your repository.
  3. Customize configuration to your needs. See below.

Configuration

Configuration of probot-auto-merge is done through .github/auto-merge.yml in your repository. An example of this file can be found here. You can also see the configuration for this repository here.

The configuration has values that serve as conditions on whether or not a pull request should be automatically merged and also configuration about the merge itself. Values that serve as conditions are annotated as such below.

All conditions must be met before a PR will be automatically merged. You can get more flexibility by defining multiple rules. Rules can have multiple conditions and if any of the conditions inside a rule are met, the PR is also merged. See rules.

If the target branch is a protected branch, you must add probot-auto-merge bot to the list of People, teams or apps with push access in your branch protection rules.

Note that the default configuration options are to do nothing. This is to prevent implicit and possibly unintended behavior.

The configuration fields are as follows:

minApprovals (required, condition)

The minimum number of reviews from each association that approve the pull request before doing an automatic merge. For more information about associations see: https://developer.github.com/v4/enum/commentauthorassociation/

Possible associations: OWNER, MEMBER, COLLABORATOR, CONTRIBUTOR, FIRST_TIMER, FIRST_TIME_CONTRIBUTOR, NONE

In the example below when a pull request gets 2 approvals from owners, members or collaborators, the automatic merge will continue.

minApprovals:
COLLABORATOR: 2

In the example below when a pull request gets 1 approval from an owner OR 2 approvals from members, the automatic merge will continue.

minApprovals:
OWNER: 1
MEMBER: 2

requiredReviewers (condition, default: none)

Whenever required reviewers are configured, pull requests will only be automatically merged whenever all of these reviewers have approved the pull request.

In the example below, pull requests need to have been approved by the user ‘rogerluan’ before they will be automatically merged.

requiredReviewers:
- rogerluan

maxRequestedChanges (condition, default: none)

Similar to minApprovals, maxRequestedChanges determines the maximum number of requested changes before a pull request will be blocked from being automatically merged.

It yet again allows you to configure this per association.

Note that maxRequestedChanges takes precedence over minApprovals.

In the example below, automatic merges will be blocked when one of the owners, members or collaborators has requested changes.

maxRequestedChanges:
COLLABORATOR: 0

In the example below, automatic merges will be blocked when the owner has requested changes or two members, collaborators or other users have requested changes.

maxRequestedChanges:
OWNER: 0
NONE: 1

The default for this value is:

maxRequestedChanges:
NONE: 0

blockingBaseBranches (condition, default: none)

Whenever blocking base branches are configured, pull requests will only be automatically merged whenever their base branch (into which the PR would be merged) is not matching the patterns listed.

In the example below, pull requests that have the base branch develop or one that starts with feature- will not be merged automatically.

blockingBaseBranches:
- develop
- regex: ^feature-

Note: remove the whole section when you’re not using blocking base branches.

requiredBaseBranches (condition, default: none)

Whenever required base branches are configured, pull requests will only be automatically merged whenever their base branch (into which the PR would be merged) is matching any of the patterns listed.

In the example below, pull requests need to have the base branch master or one that starts with v{number} before they will be automatically merged.

requiredBaseBranches:
- master
- regex: ^v\d

blockingLabels (condition, default: none)

Blocking labels are the labels that can be attached to a pull request to make sure the pull request is not being merged automatically.

In the example below, pull requests that have the blocked label will not be merged automatically.

blockingLabels:
- blocked

The above example denotes literal label names. Regular expressions can be used to partially match labels. This can be specified by the regex: property in the configuration. The following example will block merging when a label is added that starts with the text blocked:

blockingLabels:
- regex: ^blocked

Note: remove the whole section when you’re not using blocking labels.

requiredLabels (condition, default: none)

Whenever required labels are configured, pull requests will only be automatically merged whenever all of these labels are attached to a pull request.

In the example below, pull requests need to have the label merge before they will be automatically merged.

requiredLabels:
- merge

The above example denotes literal label names. Regular expressions can be used to partially match labels. This requires regex: property in the configuration. The following example will requires at least one label that starts with merge:

requiredLabels:
- regex: ^merge

Note: remove the whole section when you’re not using required labels.

blockingTitleRegex (condition, default: none)

Whenever a blocking title regular expression is configured, pull requests that have a title matching the configured expression will not be automatically merged.

This is useful whenever pull requests with WIP in their title need to be skipped.

In the example below, pull requests with the word wip in the title will not be automatically merged. This also includes [wip], WIP or [WIP], but not swiping:

blockingTitleRegex: '\bWIP\b'

requiredTitleRegex (condition, default: none)

Whenever a required title regular expression is configured, only pull requests that have a title matching the configured expression will automatically be merged.

This is useful for forks, that can only create pull request text, no labels.

In the example below, pull requests with the title containing MERGE will be automatically merged. This also includes This also includes [merge], MERGE or [MERGE], but not submerge:

requiredTitleRegex: '\bMERGE\b'

blockingBodyRegex (condition, default: none)

Whenever a blocking body regular expression is configured, pull requests that have a body matching the configured expression will not be automatically merged.

This is useful whenever pull requests with a certain string in their body need to be skipped.

In the example below, pull requests with the body containing do-not-merge will not be automatically merged. This also includes labels: do-not-merge, LABELS: DO-NOT-MERGE or some more text, but do-not-merge, but not do-not-merge-just-kidding:

blockingBodyRegex: '(^|\\s)do-not-merge($|\\s)'

requiredBodyRegex (condition, default: none)

Whenever a required body regular expression is configured, only pull requests that have a body matching the configured expression will automatically be merged.

This is useful for forks, that can only create pull request text, no labels.

In the example below, pull requests with the body containing ok-to-merge will be automatically merged. This also includes labels: ok-to-merge, LABELS: OK-TO-MERGE or some more text, but ok-to-merge, but not not-ok-to-merge:

requiredBodyRegex: '(^|\\s)ok-to-merge($|\\s)'

reportStatus (default: false)

The status of the auto-merge process will be shown in each PR as a check. This can be especially useful to find out why a PR is not being merged automatically.

To enable status reporting, add the following to your configuration:

reportStatus: true

updateBranch (default: false)

Whether an out-of-date pull request is automatically updated. It does so by merging its base on top of the head of the pull request. This is similar to the behavior of the ‘Update branch’ button.

updateBranch is useful for repositories where protected branches are used and the option Require branches to be up to date before merging is enabled.

Note that this only works when the branch of the pull request resides in the same repository as the pull request itself.

In the example below automatic updating of branches is enabled:

updateBranch: true

deleteBranchAfterMerge (default: false)

Whether the pull request branch is automatically deleted. This is the equivalent of clicking the ‘Delete branch’ button shown on merged pull requests.

Note that this only works when the branch of the pull request resides in the same repository as the pull request itself.

In the example below automatic deletion of pull request branches is enabled:

deleteBranchAfterMerge: true

mergeMethod (default: merge)

In what way a pull request is merged. This can be:

  • merge: creates a merge commit, combining the commits from the pull request on top of the base of the pull request (default)
  • rebase: places the commits from the pull request individually on top of the base of the pull request
  • squash: combines all changes from the pull request into a single commit and places the commit on top of the base of the pull request

For more information see https://help.github.com/articles/about-pull-request-merges/

mergeMethod: merge

mergeCommitMessage (default: none)

Optionally specify the merge commit message format. The following template tags are supported:

  • {title}: The pull request title at the moment it is merged
  • {body}: The pull request body at the moment it is merged
  • {number}: The pull request number
  • {branch}: The name of the source branch
  • {commits}: A list of merged commits

When this option is not set, the merge commit message is controlled by GitHub and uses a combination of the title of the pull request when it was opened (note that later changes to the title are ignored) and a list of commits.

This settings is ignored when mergeMethod is set to rebase.

mergeCommitMessage: |
{title} (#{number})
{body}

rules (default: none)

Rules allow more flexibility configuring conditions for automatically merging. Each rule is defined by multiple conditions. All conditions inside a rule must be met before a rule triggers a merge. Any of the defined rules can trigger a merge individually.

An example of a configuration with 2 rules that will trigger a merge upon 1 approval from an owner or a merge label:

rules:
- minApprovals:
OWNER: 1
- requiredLabels:
- merge

This can be combined with conditions on global level, as the global conditions will take precedence. The following example will not trigger a merge when a PR has the blocking label, regardless what the rules say:

blockingLabels:
- blocking
rules:
- minApprovals:
OWNER: 1
- requiredLabels:
- merge

Note: remove the whole rules section when you’re not using any rules.

requiredAuthorRole (default: none)

Using the requiredAuthorRole condition you can specify conditions based on the role of the pull request author. For instance, using rules, one can be more loose when the author is an owner, and more restrictive otherwise.

Here’s an example of a configuration that requires acceptance of 2 owners or 1 owner if the other owner made the PR:

rules:
- requiredAuthorRole: OWNER
minApprovals:
OWNER: 1
- minApprovals:
OWNER: 2

Development

Setup

# Install dependencies
npm install

# Run typescript
npm run build

Testing

npm run test

or during development:

npm run test:watch

Running

See https://probot.github.io/docs/development/#configuring-a-github-app

npm run build && npm run dev

Running on Docker

This will build and run the app on a container called probot-auto-merge:

npm run docker

To just build the container image:

npm run docker:build

To run the built image:

npm run docker:run

Running the linter

This will run the linter, pointing out the infractions, but it won’t fix them automatically.

npm run lint

Deployment

To deploy probot-auto-merge yourself, please follow the guidelines defined by Probot on deploying GitHub applications.

The permissions and events needed for the app to function can be found below.

Permissions

  • Administration: Read-only
  • Checks: Read & write
  • Contents: Read & write
  • Issues: Read & write
  • Metadata: Read-only
  • Pull requests: Read & write
  • Commit statuses: Read-only
  • Members: Read-only

Events

  • Check run
  • Check suite
  • Label
  • Pull request
  • Pull request review
  • Pull request review comment
  • Status

Contributing

If you have suggestions for how probot-auto-merge could be improved, or want to report a bug, open an issue! We’d love all and any contributions.

For more, check out the Contributing Guide.

License

ISC © 2018 Bob van der Linden bobvanderlinden@gmail.com (https://github.com/bobvanderlinden/probot-auto-merge)

auto-label-merge-conflicts

A Github action to auto-label PRs with merge conflicts

Purpose

This action checks all open Pull Requests for merge conflicts and marks them with a Github label.

Once a conflict is resolved the label is automatically removed.

The typical use case is to run this action post merge (e.g. push to master) to quickly see which other PRs are now in conflict.

We use this setup e.g. on our monorepo at Comtravo. Instead of a grumpy CTO pinging developers to fix their merge conflicts there’s now a shiny bot.

Set up

To configure the action on your repo you have to do 2 things:

  1. pick a Github label that should be used to mark PRs with conflicts

This label will then be managed by this action. It will be added to PRs with merge conflicts and removed from PRs without conflicts.

  1. configure the new workflow by creating a YML config file in your .github/workflows folder:
on:
push:
branches:
- master
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: mschilde/auto-label-merge-conflicts@master
with:
CONFLICT_LABEL_NAME: "has conflicts"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MAX_RETRIES: 5
WAIT_MS: 5000

The label from step 1 should be referenced in the parameter CONFLICT_LABEL_NAME

Take a look at this repo for an example setup.

Arguments:

  • MAX_RETRIES: optional (default 5)
  • WAIT_MS: optional (default 5000)

Limitations

Github does not reliably compute the mergeable status which is used by this action to detect merge conflicts.

If master changes the mergeable status is unknown until someone (most likely this action) requests it. Github then tries to compute the status with an async job.

This is usually quick and simple, but there are no guarantees and Github might have issues. You can tweak MAX_RETRIES and WAIT_MS to increase the timeout before giving up on a Pull Request.

Local dev setup

To play around with the code base, you need Docker and make set up locally.

Run make build, make develop, then yarn install.

How to use PR Valet

Step 1: Install PR Valet. Step 2: Add the valet:merge label to your pull request. Step 3: Work on your other tasks while PR Valet takes care of merging your pull request.

https://docs.mergify.io/

https://snyk.io/

文章作者: CC康纳百川
文章链接: https://blog.ccknbc.cc/posts/github-automatically-merges-pull-requests-notes/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
打赏
  • 三合一
    三合一
  • 爱发电
    爱发电

评论
目录
  1. 1. automerge-action
    1. 1.1. Usage
    2. 1.2. Configuration
    3. 1.3. Supported Events
    4. 1.4. Limitations
    5. 1.5. Debugging
    6. 1.6. License
  2. 2. bulldozer
    1. 2.1. Contents
    2. 2.2. Behavior
    3. 2.3. Configuration
      1. 2.3.1. bulldozer.yml Specification
    4. 2.4. FAQ
      1. 2.4.0.1. Can I specify both ignore and trigger?
      2. 2.4.0.2. Can I specify the body of the commit when using the squash strategy?
      3. 2.4.0.3. What if I don’t want to put config files into each repo?
      4. 2.4.0.4. Bulldozer isn’t merging my commit when it should, what could be happening?
      5. 2.4.0.5. Bulldozer isn’t updating my branch when it should, what could be happening?
      6. 2.4.0.6. Can Bulldozer work with push restrictions on branches?
  3. 2.5. Deployment
    1. 2.5.1. GitHub App Configuration
    2. 2.5.2. Operations
    3. 2.5.3. Example Files
    4. 2.5.4. Migrating: Version 0.4.X to 1.X
  4. 2.6. Development
  5. 2.7. Contributing
  6. 2.8. License
  • 3. probot-auto-merge
    1. 3.1. Usage
    2. 3.2. Configuration
      1. 3.2.1. minApprovals (required, condition)
      2. 3.2.2. requiredReviewers (condition, default: none)
      3. 3.2.3. maxRequestedChanges (condition, default: none)
      4. 3.2.4. blockingBaseBranches (condition, default: none)
      5. 3.2.5. requiredBaseBranches (condition, default: none)
      6. 3.2.6. blockingLabels (condition, default: none)
      7. 3.2.7. requiredLabels (condition, default: none)
      8. 3.2.8. blockingTitleRegex (condition, default: none)
      9. 3.2.9. requiredTitleRegex (condition, default: none)
      10. 3.2.10. blockingBodyRegex (condition, default: none)
      11. 3.2.11. requiredBodyRegex (condition, default: none)
      12. 3.2.12. reportStatus (default: false)
      13. 3.2.13. updateBranch (default: false)
      14. 3.2.14. deleteBranchAfterMerge (default: false)
      15. 3.2.15. mergeMethod (default: merge)
      16. 3.2.16. mergeCommitMessage (default: none)
      17. 3.2.17. rules (default: none)
      18. 3.2.18. requiredAuthorRole (default: none)
    3. 3.3. Development
      1. 3.3.1. Setup
      2. 3.3.2. Testing
      3. 3.3.3. Running
      4. 3.3.4. Running on Docker
      5. 3.3.5. Running the linter
    4. 3.4. Deployment
      1. 3.4.1. Permissions
      2. 3.4.2. Events
    5. 3.5. Contributing
    6. 3.6. License
  • 4. auto-label-merge-conflicts
    1. 4.1. Purpose
    2. 4.2. Set up
      1. 4.2.1. Arguments:
    3. 4.3. Limitations
    4. 4.4. Local dev setup
  • 5. How to use PR Valet
  • 6. https://docs.mergify.io/
  • 7. https://snyk.io/
  • 扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/google-adsense-configuration-manual/index.html b/posts/google-adsense-configuration-manual/index.html new file mode 100644 index 000000000..fd5c2463f --- /dev/null +++ b/posts/google-adsense-configuration-manual/index.html @@ -0,0 +1,19 @@ +Google Adsense 配置手册 | CC的部落格

    Google Adsense 配置手册

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀,自动同步更新至CC 的部落格

    写在前面

    当作是一个公告了,如果你“不幸”点开了这篇文章,那么麻烦您动动小手,关闭您的广告屏蔽插件,或者添加本站到白名单,然后刷新一下点击一次广告(虽然还是有几率看不到广告)后继续浏览本篇文章

    缘起

    Q:如果你的流量还可以,自认为文章写的还不错,有了一定的阅读基数,那么你会选择开启赞赏功能还是开启 Google Adsense 呢?

    当然如果有人愿意赞赏支持你继续创作,或者是你真的帮助别人解决了一些问题,那么可能会收到一些打赏;但对于我这种产出有限的来说,开启广告或者是更好的选择(我已经厚脸皮求您暂时关掉广告插件了,如果还是不愿意点击广告,那真的是不喜欢广告了);因此博客成立以来便一直未提供赞赏二维码,广告也只是申请的那段时间开过一段时间,直到最近,才加入了爱发电(但有手续费,所以不是很推荐);即使很早就开通了 Adsense ,但因为身在大陆,还是要遵守相关法律法规,毕竟也公安备案了,如果不注意就可能引来麻烦,所以如何设置好 Adsense 一直困扰着我。

    配置

    阅读体验

    关于如何配置其实很简单,只是因为我们是博客,所以还是要注意用户阅读体验,因此我们需要为移动设备优化广告尺寸,并且将广告数量调至最低(自动广告),关闭影响阅读体验的锚定广告和穿插广告等 至于排除网页,因为开启了匹配内容,那么我们有必要屏蔽掉 404 页面 此外,如果你使用的是自定义广告单元广告,按照使用体验,可在首页放置信息流广告,侧边栏放置展示广告,文章页放置内嵌广告(在对应位置插入对应代码)

    屏蔽内容

    1. 敏感类别,例如涉黄涉政内容,即使我本人还算比较开放,但网站广告的受众我无法保证,所以为了未成年的健康成长,我会屏蔽掉所有敏感类别

    1. 普通类别,最为典型的就是赌博和网络连接类应用,但即使这样屏蔽掉,还是偶尔会有漏网之鱼,因此我会定期手动屏蔽不合适的广告

    其实类别还有其他,后续也会慢慢更新,只是这张图就不再更新了,因为长截图吗(懒),所以看下面的图片就好了

    说真的,关于这个社交网络在线社区类别我觉得有必要考量一下,有待后续观察中,因为展示百分比算少的,但是占收入很高,所以可能和色情相关联?

    总之,屏蔽类别关键词:软件烟草酒精

    还有存疑的类别就是网络安全软件浏览器电视节目,因为我们看到的不符合法律要求的广告,在我看来,他们应该属于这些范畴内

    隐私保护

    除了屏蔽敏感内容以外,还得注意隐私保护,因此还可以针对性做一点设置,不提供个性化广告服务(即使知道这样会减少广告点击率,但本来也就没什么点击率);此外为了网页加载速度和阅读体验,关闭动画展示、VPAID 广告

    展望未来

    开通广告当然还可以激励着自己,希望能坚持产出以便对得起我展示广告,虽然还不一定看得到,但确实展示量够了还是有一点收入的,哪怕每天 0.01 $,十年过去,应该够域名费用了吧(笑死,还是不够),但我还不配,或许那个时候我的博客访问量激增(当然掌握了更多知识,分享了更多内容)。

    当然这个世上没有如果,既然买了十年的域名,就要好好做下去,但愿十年后博客还有人访问评论,交流心得!此外,如果你知道更好的广告屏蔽类别组合,欢迎留言,因为真的不想再突然蹦出色情和梯子广告了,不然别人还以为我是什么不正经博客,本来访问量就低,就怕三秒就走了,名声还坏了!!!

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/google-adsense-configuration-manual/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/hexo-butterfly-algolia/index.html b/posts/hexo-butterfly-algolia/index.html new file mode 100644 index 000000000..8e6bb1b78 --- /dev/null +++ b/posts/hexo-butterfly-algolia/index.html @@ -0,0 +1,19 @@ +Hexo Butterfly Algolia 搜索的使用 | CC的部落格

    Hexo Butterfly Algolia 搜索的使用

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文介绍了 Hexo Butterfly 主题下 Algolia 搜索的使用

    本文首发在语雀 自动同步更新至CC 的部落格

    注册账号

    前往 Algolia 官网注册一个账号,新建 应用和 index 数据中心建议选择新加坡或香港,当然根据你自己情况而定

    安装插件

    npm install hexo-algolia --save
    npm install hexo-algoliasearch --save

    分别是 hexo-algoliahexo-algoliasearch,他们的介绍分别为

    Index your hexo website content to Algolia Search.
    🔎 A plugin to index posts of your Hexo blog on Algolia

    也就很明显了,如果你想要全站搜索可选择前者,如果你只想搜索文章两者兼可。但前者不能将文章内容作为索引上传(其实老版本是支持的,但因为索引大小限制,在新版本取消索引了文章内容),后者目前仍可全文上传。然后就是 HEXO 配置文件中添加以下内容,下文基本以 hexo-algoliasearch 为例,因为我个人认为访客只会搜文章吧(事实上是搜索根本没人用,毕竟也根本没人访问),hexo-algolia 可查看官方文档,注意配置和命令的区别

    _config.yml :

    algolia:
    appId: "Z7A3XW4R2I"
    apiKey: "12db1ad54372045549ef465881c17e743"
    adminApiKey: "40321c7c207e7f73b63a19aa24c4761b"
    chunkSize: 5000
    indexName: "my-hexo-blog"
    fields:
    - content:strip:truncate,0,500
    - excerpt:strip
    - gallery
    - permalink
    - photos
    - slug
    - tags
    - title

    为了保险,识别到插件,还可以加入以下内容

    plugins:
    - hexo-algoliasearch

    去主题配置文件打开 Algolia 搜索,记得关闭本地搜索,二者只能取其一!

    _config.butterfly.yml :

    # Algolia search
    algolia_search:
    enable: true
    hits:
    per_page: 3

    # Local search
    local_search:
    enable: false

    然后来看以下具体的参数配置获取方式appIdapiKeyadminApiKey可在 API Keys 页面获取,注意保管好你的 Admin Key,不要让其他人知道,不建议直接写在配置中 对于 Windows 系统,如果你不想每次都进行设定变量操作,可以添加ALGOLIA_ADMIN_API_KEY到系统的环境变量中 而 hexo-algolia 插件环境变量名称为 HEXO_ALGOLIA_INDEXING_KEY 注意根据对应的文档更改,当然也可以使用命令行工具

    # Windows
    ## 微软的 powershell)
    $env:ALGOLIA_ADMIN_API_KEY = ""

    ## cmd
    建议不用 cmd,正经人不用 cmd

    # Linux
    ## sh/bash
    export ALGOLIA_ADMIN_API_KEY=

    ## fish
    set -xg ALGOLIA_ADMIN_API_KEY ""

    如果你和我一样使用的自动部署,例如 Github Actions,你可以在工作流中一开始或者对应的步骤添加环境变量,记得 Secrets 中也要添加哦

    jobs:
    deploy:
    name: Deploy Hexo Public To Pages
    runs-on: ubuntu-latest
    env:
    TZ: Asia/Shanghai
    ALGOLIA_ADMIN_API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }}

    或者使用

    export ALGOLIA_ADMIN_API_KEY=…
    export HEXO_ALGOLIA_INDEXING_KEY=…

    indexName 即你开始新建的索引名称 其他内容保持默认即可,但对于fields

    配置示例

    这里选择不截取上传全文,并且删除 html 标签,只留下有用的搜索内容

    fields:
    - content:strip
    - excerpt:strip
    - gallery
    - permalink
    - photos
    - slug
    - tags
    - title

    但对于博客来说,没人会按照 tags photos(或者 cover)来搜索吧,所以有些内容不必要上传,并如果你和我一样有多个镜像站,在不改源码(algolia.js)的情况下,不会使用 permalink 而使用 path(改源码可以使用 slug,但没必要),并且只留下必要的内容,如下所示:

    algolia:
    appId: "947RX7HP3E"
    apiKey: "9114b3fa2a3307b2cc8eec7e3ae5a8ea"
    chunkSize: 5000
    indexName: "ccknbc-blog"
    fields:
    - path
    - title
    - content:strip

    这样有了标题,全文内容,路径即可在不同镜像站找到对应的页面,而不是跳到主站,当然你选择跳到主站无可厚非。

    使用命令

    hexo algolia
    而在这之前还需要hexo g生成文件
    所以具体使用命令就是
    hexo cl && hexo g && hexo algolia
    或者在未安装 HEXO CLI 的情况下使用以下命令
    npm run clean && npm run build && hexo algolia -n && gulp

    可选配置

    是否删除之前建立好的索引重新建立索引?

    hexo algolia -n
    或者
    hexo algolia --no-clear

    注意查看命令行输出信息,然后去官网检查索引是否生成 事实上到这里已经可以获得下图所示的搜索效果(这是冰老师博客的效果,它使用的是 hexo-algolia,毕竟有关于我界面)

    Algolia 配置

    这里不细节讲,你可以查阅官方文档,虽然有些过时的参数,但结合 Upgrade from v2 to v3 还是勉强能用,蝴蝶已经做好了高亮标题,虽然会查询文章内容,但并不会高亮文章内容节选,我们要做的就是修改部分 js 内容,并对应的设置好 Algolia,以便按照我们要求的优先顺序展示搜索结果,而不是默认的很奇怪的排序,毕竟针对中文分词他是一个一个分不能按照英语那样,针对英文我们可以开启分词查询,驼峰查找而不是盲目的匹配整个单词,并且允许拼错字母或汉字的情况存在,这些都是一个搜索系统要考虑的问题。然后针对搜索速度,我们可以对文章内容进行切片或者属性的刻画,但 V2 所支持的功能实在太少,派的上用场的大概就是 匹配的字词内容,匹配度,匹配内容的摘录(默认 10 个字词),还有高级搜索用法的启用。

    JS 修改

    主题 4.0.0 以下版本

    到这里还没有结束,如果你这样操作就会有一个问题,假设你的访问流量很大,有很多人用搜索功能,那么免费的 1 万次搜索额度可能不够一个月的使用,需要按下ENTER键再执行搜索而不是实时搜索,因此可以稍作修改(blog\themes\butterfly\source\js\search\algolia.js) js 的部分内容,不想动源码的可以保存到其他与主题不冲突的路径,然后更换 CDN 地址即可主要修改以下内容,然后就是排版问题改了改位置,不喜欢的可以不改,很直白就不用过多解释了,这样就可获得和本博客一样的搜索效果了

      search.addWidget(
    instantsearch.widgets.searchBox({
    container: '#algolia-search-input',
    reset: false,
    magnifier: false,
    + searchOnEnterKeyPressOnly: true,
    placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder
    })
    )
    search.addWidget(
    instantsearch.widgets.hits({
    container: '#algolia-hits',
    templates: {
    item: function (data) {
    const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
    return (
    '<a href="' + link + '" class="algolia-hit-item-link"><b>' +
    data._highlightResult.title.value + '</b><br>'
    + + data._snippetResult.contentStrip.value + '<br>( 匹配字词 : '
    + + data._highlightResult.contentStrip.matchedWords + ' ) | ( 匹配等级 : '
    + + data._highlightResult.contentStrip.matchLevel + ' )</a>'
    )
    },

    主题 4.0.0 以上版本

    已经升级到 V4 版本,那么一些特性就可以使用了,修改内容其实差不多,只是建议对于第 87 行的页数限制,主要是为了手机上排版美观,不会转到下一行,但是这样会有一个问题,如果结果超过 5 页,那么将无法显示,最后一页代表第 5 页,所以我个人会选择删掉这个参数限制,同时合并删除了部分代码,以及使用 widget 的 powerby 组件而不是官方的 svg 代码解决方案。另外因为新版官方的每次访问网站都会有一次全局请求,这在消耗免费额度的同时,也影响网站加载的速度,所以修改默认行为为按下回车后再请求同样的部分参数发生了改变(L55-59),可以自行比对或查看官方文档,也可以直接引用我的

    特别提一嘴 官方切片方式对我来说 140 个字太长了,所以如果可以接受就用官方的,不用做其他更改,但想要和我的显示方式一样,就注意配置好切片,默认是 10 个词符,毕竟有现成的切片高亮处理可以用,就没必要再来一次了

    另外,新版浏览器支持搜索并定位高亮处理,所以对跳转链接也做了处理,算是弥补了一点不能精准定位的缺陷,比如点击如下链接它会跳转到搜索结果对应的位置,至于前后匹配多少字符你们自行修改,但也是处于不太好用的状态,毕竟是分片还是有点奇怪,对英文来说应该是单词识别,只是中文恰巧是另一标准,单字变成了词

    #:~:text=勿滥用-,表情,-符号和

    CDN:
    # search
    algolia_js: https://cdn.jsdelivr.net/gh/CCKNBC/ccknbc.github.io/js/search/algolia.js
    window.addEventListener("load", () => {
    const openSearch = () => {
    const bodyStyle = document.body.style;
    bodyStyle.width = "100%";
    bodyStyle.overflow = "hidden";
    btf.animateIn(document.getElementById("search-mask"), "to_show 0.5s");
    btf.animateIn(
    document.querySelector("#algolia-search .search-dialog"),
    "titleScale 0.5s"
    );
    setTimeout(() => {
    document.querySelector("#algolia-search .ais-SearchBox-input").focus();
    }, 100);

    // shortcut: ESC
    document.addEventListener("keydown", function f(event) {
    if (event.code === "Escape") {
    closeSearch();
    document.removeEventListener("keydown", f);
    }
    });
    };

    const closeSearch = () => {
    const bodyStyle = document.body.style;
    bodyStyle.width = "";
    bodyStyle.overflow = "";
    btf.animateOut(
    document.querySelector("#algolia-search .search-dialog"),
    "search_close .5s"
    );
    btf.animateOut(document.getElementById("search-mask"), "to_hide 0.5s");
    };

    const searchClickFn = () => {
    document
    .querySelector("#search-button > .search")
    .addEventListener("click", openSearch);
    };

    const searchClickFnOnce = () => {
    document
    .getElementById("search-mask")
    .addEventListener("click", closeSearch);
    document
    .querySelector("#algolia-search .search-close-button")
    .addEventListener("click", closeSearch);
    };

    const algolia = GLOBAL_CONFIG.algolia;
    const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName;
    if (!isAlgoliaValid) {
    return console.error("Algolia setting is invalid!");
    }

    const search = instantsearch({
    indexName: algolia.indexName,
    searchClient: algoliasearch(algolia.appId, algolia.apiKey),
    searchFunction(helper) {
    helper.state.query && helper.search();
    },
    });

    const configure = instantsearch.widgets.configure({
    hitsPerPage: algolia.per_page || 5,
    });

    const searchBox = instantsearch.widgets.searchBox({
    container: "#algolia-search-input",
    showReset: false,
    showSubmit: false,
    searchAsYouType: false,
    placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
    showLoadingIndicator: true,
    });

    const hits = instantsearch.widgets.hits({
    container: "#algolia-hits",
    templates: {
    item(data) {
    const link = data.permalink
    ? data.permalink
    : GLOBAL_CONFIG.root + data.path;
    const content = data._snippetResult.contentStrip.value;
    return `
    <a href="${link}#:~:text=${content.substring(
    content.indexOf("<mark>") - 3,
    content.indexOf("<mark>")
    )}-,${content.substring(
    content.indexOf("<mark>") + 6,
    content.indexOf("</mark>")
    )},-${content.substring(
    content.indexOf("</mark>") + 7,
    content.indexOf("</mark>") + 10
    )}" class="algolia-hit-item-link">
    <b>${data._highlightResult.title.value || "no-title"}</b>
    <br>${content}</br>
    匹配字词: <em><mark>${
    data._highlightResult.contentStrip.matchedWords
    }</mark></em> | 匹配等级: <em><mark>${
    data._highlightResult.contentStrip.matchLevel
    }</mark></em>
    </a>`;
    },
    empty: function (data) {
    return (
    '<div id="algolia-hits-empty">' +
    GLOBAL_CONFIG.algolia.languages.hits_empty.replace(
    /\$\{query}/,
    data.query
    ) +
    "</div>"
    );
    },
    },
    });

    const stats = instantsearch.widgets.stats({
    container: "#algolia-info > .algolia-stats",
    templates: {
    text: function (data) {
    const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
    .replace(/\$\{hits}/, data.nbHits)
    .replace(/\$\{time}/, data.processingTimeMS);
    return `<hr>${stats}`;
    },
    },
    });

    const powerBy = instantsearch.widgets.poweredBy({
    container: "#algolia-info > .algolia-poweredBy",
    });

    const pagination = instantsearch.widgets.pagination({
    container: "#algolia-pagination",
    totalPages: algolia.totalPages,
    templates: {
    first: '<i class="fa-solid fa-angle-double-left" title="第一页"></i>',
    last: '<i class="fa-solid fa-angle-double-right" title="最后一页"></i>',
    previous: '<i class="fa-solid fa-angle-left" title="上一页"></i>',
    next: '<i class="fa-solid fa-angle-right" title="下一页"></i>',
    },
    });

    search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]); // add the widgets to the instantsearch instance

    search.start();

    searchClickFn();
    searchClickFnOnce();

    window.addEventListener("pjax:complete", () => {
    getComputedStyle(document.querySelector("#algolia-search .search-dialog"))
    .display === "block" && closeSearch();
    searchClickFn();
    });

    window.pjax &&
    search.on("render", () => {
    window.pjax.refresh(document.getElementById("algolia-hits"));
    });
    });

    效果预览

    (这个是因为我修改了源码,实际上也能通过修改 JS 实现,但大多数人不会关心这些搜索小贴士) 对于中文它当作单字匹配 允许拼写错误

    特别说明

    因两个月前已申请通过,本博客已切换至不限搜索次数的DocSearch!同时也加入了开源计划,但因为 10DSN 太香了,虽然 instantsearch 可玩性更好,但我也只申请了 200k/月的额度(虽然可以增加),所以为了即时搜索我还是选择了白嫖,而且设定为每天自动爬取的话,省去了生成索引上传的这一步骤,节省了自动部署的时间。而且爬取到数据后,前端我并非一定要使用 docsearch 方案,用 instantsearch 配合其他插件也不是不可以。

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/hexo-toss/index.html b/posts/hexo-toss/index.html new file mode 100644 index 000000000..4f8ea8391 --- /dev/null +++ b/posts/hexo-toss/index.html @@ -0,0 +1,19 @@ +HEXO 折腾 | CC的部落格

    HEXO 折腾

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    HEXO 折腾个人目前使用主题为 Butterfly 3.0.1版本,HEXO 5.0.2版本

    请按照以下步骤依次安装相应依赖和框架

    搭建步骤

    安装 Node.js

    什么是 Node.js ? 这得从什么是 JS 说起,JS 也就是 JavaScript。(为什么有种从盘古开天辟地开始的感觉)没错,JavaScript 就是网页的盘古。JavaScript 是一种编程语言,我们所见到的网页中的交互和逻辑处理几乎都是由 JavaScript 完成。 JavaScript 语法简单,易学易用。(当然也请不要小瞧它,虽然它入门门槛低,但上限同样也很高。包括但不限于实现网站前后端,手机桌面应用程序,机器学习,计算机图形学等。)在 Node.js 诞生前,JavaScript 都运行于浏览器端。也就是说,它是鱼,浏览器是装满了水的水缸。 2008 年,Chrome V8 诞生。2009 年,Node.js 诞生。并成为 GitHub 早期最著名的开源项目。GitHub 可能大家已有所了解,后续再说。 Node.js 便是一个基于 Chrome V8 引擎的 JavaScript 运行环境。(当年第一次看到这句话时,我也一脸懵逼。)按照我的理解,JavaScript 是鱼,Chrome V8 就是抽水机,Node.js 则把这台抽水机也装在你电脑上。于是你的电脑也有了 Node.js 这个和浏览器相似的水缸,也可以在里面运行 JavaScript 了!当然 Node.js 和浏览器端还是因为自身定位和一些历史原因而有些许区别的,不再展开。 Node.js | 百度百科 JavaScript | MDN

    下载| Node.js

    建议下载长期支持版而非当前发布版(因为如果是最新版,容易出现一些奇妙的 bug)。

    全部默认下一步进行安装。

    Windows 打开命令提示符,macOS 打开终端。(= =,这个不会就请百度吧。) Linux 用户右上角关闭本标签页。

    后续如提到输入命令,均默认指打开终端进行输入。

    输入 node --version,如果得到的版本号与你方才安装的一致,那么 Node.js 就已经成功安装。

    Node.js 安装成功时也默认安装了 npm,在此后将会用到。 npm 是随 Node.js 一起被安装的包管理工具,你可以理解成 Node.js 自带的应用商店。

    对了,国内使用 npm 可能很慢。

    你可以考虑切换为 taobao 镜像源。

    npm config set registry https://registry.npm.taobao.org

    npm & yarn 常用包与命令

    Git 与 GitHub

    安装 Git

    Visual Studio Code,简称 VS Code。目前最为强大易用的编辑器,轻量且快速。(宇宙第一编辑器)注意:它并不是我们常常听到的 VS,VS 常常指的是 Visual Studio,是一个功能强大的 IDE(集成开发环境),体积也相比 VS Code 都要大上一个量级。

    在此之前,我建议你先安装 VS Code。因为安装 Git Bash 时,可以设置 VS Code 作为默认编辑器。

    Git 是一个开源的分布式版本控制系统,由 Linus Torvalds(同时也是 Linux 的作者)为了管理 Linux 开发而开发。简而言之,是一个版本管理工具。譬如设计师设计好了第三版的海报,客户却说还是要第一版吧,这时便可以通过 Git 快速回退到最初的版本。你只需要把每次更改的状态(Git 会自动进行检测,你只要掌握基础的几条命令就可以了)告诉 Git,而不需要每个版本都保存一份压缩包,既方便也能大大节约空间。(当然这主要只对代码文本起作用,因为 Git 的本质是记录各行代码的增减,倘若是像视频、海报这类二进制文件来说便体现不出丝毫优势了。当然想要应对这种场景还有 Git LFS。)

    下载 Git 并安装(如果国内速度太慢,可以试试这里

    macOS 用户可以下载官网的安装包进行安装,也可以直接安装 App Store 的 Xcode(附带会安装 Git,但是比较大)。

    类似的工具还有:SVN。但始终更推荐 Git,因为它功能更为强大且它的背后还有更强大的生态:GitHub。

    注册 GitHub

    这一部分内容,你也可以放到本地调试并预览成功后并打算线上部署的时候,再回过头来看。

    GitHub 一听便与 Git 有所渊源。Git 在英文中是懒人、饭桶之意。Hub 则是中心、集线器的意思。譬如 USB 集线器就是 USB Hub。所以 GitHub 就是饭桶中心(大雾)。 GitHub 是全世界最大的开源项目与代码托管平台,也是众多开发者的交流场所。还是全球最大的同性交友网站。而代码托管本身用到的正是上文提到的 Git 技术。

    注册 GitHub 账号。(虽然都是英文,但不必畏惧,也并不会造成使用障碍,只要记得最常用的选项含义即可,以及善用手头的翻译软件。)

    注意:注册时的英文用户名将成为你可以使用的免费域名前缀。

    登录 GitHub。

    为什么要用 GitHub?对于平民玩家来说,在初次尝试建立自己的网站时,也许并不会有闲钱或者说决心来购买自己的服务器与域名。而 GitHub 则提供了 GitHub Pages 这一服务。用户们可以利用这一服务,部署自己的静态站点。

    点击右上角的 + -> New repository 新建仓库。

    仓库名称务必为 你的用户名.github.io,用户名是英文,大小写无所谓,但建议统一小写。(因为你会发现时常切换大小写很麻烦)

    为什么必须这个作为仓库名? GitHub Pages 服务的命名规范,同时若您没有自己的域名,使用 Github 提供的服务的话,请务必将此仓库设为公开,同时它也将成为你的专属域名。当然,你也可以购置自己的专属域名并用它来提供内容。

    点击 Create repository

    安装 Hexo

    Hexo

    为嘛使用 Hexo ? Hexo 是一个快速、简洁而强大的博客框架,基于 Node.js,同样托管于 GitHub 之上。生态中拥有众多插件主题。你可以基于它快速生成一些静态页面。你可以使用别人的各种主题与插件,也可以自己定制开发想要的功能。 为什么不是…? 其他常用的博客框架还有 WordPressTypechoGhost 等,但这些往往都需要购置自己的服务器,而无法静态化地部署到 GitHub Pages 上。(当然,相应的功能和灵活性也大大提升。)静态化站点还有一个优势就是访问速度往往更快。静态网站生成器还有 VuepressGatsby 等。但这些多是为了写文档而量身定制的,你也可以使用它们,但是相较 Hexo 的博客定位,它们关于博客的插件和主题以及解决办法会少得多。 Hexo 提供的功能与 Hugo 几乎都有,(生成大量文件时,甚至比 Hexo 更快)不过它是基于 GO 语言。日后你想对自己的网站进行自定义,即便是 Hugo,你编写前端的交互仍旧需要使用 JavaScript,所以选择基于 JavaScript 的 Hexo 可以降低学习成本。(你若对 GO 有兴趣,仍然可以尝试使用 Hugo,但本教程将不会针对 Hugo 进行展开。)所以对于新手来说,使用 Hexo 作为起始点,不失为一个好选择。(当然如果你有钱租服务器,并希望快速上手的话,就可以考虑考虑 WordPress 或者 Typecho)这里顺带推荐一下小伙伴 染川瞳 的 WordPress 主题 Sakurairo阔落 的 Typecho 主题 miracles,都是很漂亮的主题。

    在终端中输入以下命令:

    npm install hexo-cli -g
    # 如果安装失败,可能是没有权限,可以尝试头部加上 sudo 重新执行
    # sudo npm install hexo-cli -g

    install 自然是安装。 hexo-cli 则是 hexo 的终端工具,可以帮助你生成一些模版文件,之后再用到。 -g 代表的是全局安装。也就是在任何地方都可以使用,否则会只能在安装的目录下使用。

    此时,请先通过 cd 进入你本地电脑打算存储网站代码的文件夹目录。(或者右键文件夹 Git Bash Here)

    cd | DOS 命令 cd (LINUXSHELL 命令)

    譬如:

    注意:这里是你自定义的目录,请不要复制粘贴

    # '#' 字符后的文字代表注释,不需要输入
    # Windows
    cd C:\Users\CCKNBC\Documents\GitHub\
    #实际上我用的是D:blog目录,按需选择即可
    # macOS
    # cd /Users/yunyou/github/

    接下来输入:

    hexo init 你的名字.github.io

    hexo 正是因为我们之前安装了 hexo-cli 这一个包,所以我们可以在终端中使用 hexo 这一命令。 init 初始化博客的模版文件。后面跟的是你要新建的文件夹,最好和你此前新建的仓库名一致。

    # 进入你的博客文件夹
    cd 你的名字.github.io
    # 默认安装所有 `package.json` 文件中提到的包
    npm install
    # 你也可以缩写成 hexo s
    hexo server

    server 代表开启本地的 Hexo 服务器,这时你就可以打开浏览器,在地址栏中输入 localhost:4000 就可以看到本地的网页了。

    Ctrl + C 中断服务器的运行。

    至此,基础的模版页面便已经搭建好了。

    主题安裝

    使用 Hexo 主题

    Hexo 默认提供的是 hexo-theme-landscape 主题。默认主题样式简单,功能较少。所以大多数人并不会使用默认主题。

    Git 安装

    在博客根目录里安装稳定版master分支【推荐】

    git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

    如果想要安装比较新的dev分支,可以

    git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

    npm 安装

    此方法只支持Hexo 5.0.0以上版本

    在博客根目录里

    npm i hexo-theme-butterfly

    应用主题

    修改 hexo 配置文件_config.yml(根目录),把主题改为Butterfly(注意配置要和你的主题文件夹名大小写完全一致哦)

    theme: butterfly

    如果你沒有pug以及stylus的渲染器,请下载安装:

    npm install hexo-renderer-pug hexo-renderer-stylus --save

    在进行配置修改之前,为了以后主题通过 git pull 平滑升级,请不要随意改动主题源码,虽然你可以通过强制合并来解决,但保险点总是没错的,并且由于主题的**约定>配置**特性,因此我们通常在 Hexo 根目录**sorce/_data**下把主题的**_config.yml**(主题目录)复制过来,并且重命名为**butterfly.yml**,然后再对 butterfly.yml 进行修改即可

    有了上面的基础,我们就可以根据对应的文档修改相应的配置了,以下不再赘述

    生成静态文件

    至今我们的工作都是在本地进行,想必你也很想放到线上与小伙伴们分享。这便轮到了 GitHub Pages 的出场,不过 GitHub Pages 只支持纯静态文件。

    所以我们需要使用以下命令先来生成站点的静态文件。

    # 如果进行多次生成,为了避免受错误缓存影响,最好使用 hexo clean 先清除一遍。
    hexo generate
    # 缩写为 hexo g

    此时你的文件夹目录下会出现 public 这个文件夹,里面存放的就是你站点的静态文件。

    与远程仓库建立关联

    接下来我们将本地的仓库与此前在 GitHub 上建立的仓库建立关联。

    git init # 初始化 Git 仓库,只需要执行一次即可

    在将其部署到 GitHub Pages 上之前,我们最好先建立一个分支。

    什么是分支? Git 提供了版本管理功能,其中还有一个分支功能,你现在可以简单地将其理解为平行世界。

    你的名字.github.io 部署后,GitHub Pages 将默认使用你的 master 分支作为静态文件部署。所以我们最好新建一个 hexo 分支(命名无所谓)用来存储 Hexo 地源代码,master 分支则用来存储部署后的静态文件。

    git checkout -b hexo

    这时便成功建立了一个 hexo 分支。(此后的工作都将在 hexo 分支下进行)

    你可以通过 git branch -v 来查看当前有哪些分支,使用 git branch 分支名 来切换到对应的分支。

    Git 学习笔记

    部署

    为了更方便的部署到 GitHub Pages,Hexo 提供了 hexo-deployer-git 插件。

    老规矩,安装。

    npm install hexo-deployer-git

    _config.yml 中配置。

    deploy:
    type: git
    repo: 你此前新建的仓库的链接 # 比如:https://github.com/YunYouJun/yunyoujun.github.io
    branch: master # 默认使用 master 分支
    message: Update Hexo Static Content # 你可以自定义此次部署更新的说明

    保存,部署!

    第一次可能需要你输入用户名与密码。密码输入的时候不会出现 ***,不要害怕,已经输入进去了。

    hexo deploy

    等待完成后,打开网址 https://你的名字.github.io 就能看到你的线上网站了。

    使用 https,http 可能无法正常打开。HTTPS 是多了安全加密的 HTTP,Chrome 浏览器已经默认会显示 http 链接为不安全。为了安全,建议开启强制 https 跳转。项目地址页面 -> Settings -> Options -> GitHub Pages -> Enforce HTTPS。(翻到下面)此时,http 网址会自动重定向到 https

    备份与自动部署

    我们当前只是将生成的静态文件部署到了云端。

    为了以防万一,我们应该将网站的源代码文件也推送到 GitHub 仓库备份。

    # 与远程 Git 仓库建立连接,只此一次即可
    git remote add origin https://github.com/你的用户名/你的名字.github.io

    接下来准备提交,这几句命令将是你以后每次备份所需要输入。

    # 添加到缓存区
    git add -A
    git commit -m "这次做了什么更改,简单描述下即可"
    # 推送至远程仓库
    git push
    # 第一次提交,你可能需设置一下默认提交分支
    # git push --set-upstream origin hexo

    每次推送都要输入这三条命令,你可能觉得有些麻烦。那么你可以编写 bash 脚本。

    譬如,在根目录下新建 update.sh

    # 如果没有消息后缀,默认提交信息为 `:pencil: update content`
    info=$1
    if ["$info" = ""];
    then info=":pencil: update content"
    fi
    git add -A
    git commit -m "$info"
    git push origin hexo

    此后更新的话,只需要在终端执行 sh update.sh 即可。

    更新麻烦,每次部署也很麻烦,可以使用持续集成进行自动部署。

    什么是持续集成?持续集成是一种软件开发实践。对软件进行自动化构建,以此来发现错误。 Travis CI 就是一个线上持续集成服务的提供商。它可以拉取你每次推送到 GitHub 上的代码,然后根据你的要求对其进行构建。我们可以趁机让它自动生成网站静态文件,然后自动帮我们部署。除此之外,你还可以使用 GitHub ActionsNetlify 等服务。 GitHub Actions 相比 Travis 等,自身便拥有仓库的 Token,不再需要额外设置,可以直接使用 secrets.GITHUB_TOKEN。推荐一个专门用来部署 gh-pages 的 Actions actions-gh-pages

    关于更多更具体的自动化部署方案和操作步骤,你可以参考我的小伙伴 ChrAlpha 的 初探无后端静态博客自动化部署方案

    他在文章中详细介绍了 Netlify 、GitHub Actions 和 Travis CI 的部署方法。

    你也可以参考 Hexo 的官方文档 将 Hexo 部署到 GitHub Pages

    我就不在此画蛇添足。


    当然还有个更简便的方法,直接参考我的 gh-pages.yml

    去掉夹在 yarn installyarn build 之间的 algolia 部分,直接粘贴到你的 .github/workflows/ 文件夹(自己新建)下 xxx.yml 文件里即可。

    推送后便可直接自动部署。

    至此,你的站点便基本搭建完成,此后继续对主题进行自定义吧。

    开始写作

    文章

    输入以下命令即可新建 xxx.md 文件。

    hexo new post xxx

    mdMarkdown 的后缀名,是一种简洁方便的文本标记语言。你只需要记住简单的几种语法,就可以快速进行编写。为什么使用 Markdown?首先 Hexo 本身就是将 Markdown 转化为静态的 Html 文件,来方便用户编写文章。 Markdown 就好似介于 Word 与 TXT 文本之间。Word 体积大、大部分功能实际上根本用不到,且最后的文档常常带有许多冗余信息。而 TXT 却无法实现加粗、标题、下划线、水平分割线等常用的功能。(这里所说的 TXT 只是一种纯文本格式的代称,实际上 Markdown 也是纯文本文件,不过通过语法和 Markdown 编译器,我们就可以看到一些简单的样式。)

    譬如本文就是通过 Markdown 编写。

    # 一级标题

    ## 二级标题

    **加粗文字**

    更多语法(虽然说是更多,但是其实也没多少):Markdown 基本语法

    这是我写的一个 Markdown 样式:star-markdown-css

    上面是渲染过后的效果,你可以与其 Markdown 的纯文本原文进行对比。

    页面

    你可以新建一些自己的自定义页面。

    譬如直接在 Hexo 目录下的 source 文件夹下直接新建 HTML 进行编写。

    也可以通过以下命令来新建页面。(当然还是 Markdown,不过也是可以在 Markdown 里写 HTML 的,也会被渲染出来。)

    hexo new page xxx

    至于对应的参数配置,请参考主题文档

    FAQ

    视频?

    没有视频,一是懒,二是文字更利于更新勘误。

    以及文章中将会频繁出现参考链接,更方便使用。

    如何绑定你的自定义域名?

    首先,你得有个自己的域名。

    避免广告嫌疑,你可以自行前往相关域名提供商购买。但是如果你有幸能看到谷歌广告(概率较小),可以考虑点一点。

    并使用 CNAME 解析到 你的名字.github.io。(当然 A 记录直接解析到 GitHub Pages IP 地址也可以。)

    Managing a custom domain for your GitHub Pages site

    Hexo 工作目录下 source 文件夹下新建 CNAME 文件(没有后缀名)。

    CNAME 即相当于告诉 GitHub 允许将 xxx.github.io 为你的域名提供服务。 source 目录下的文件除了特殊的 markdown 会被解析为 html,其余都会原样复制到生成的静态文件夹中。所以你需要在 source 文件夹下建有 CNAME,它会在生成静态文件时,将 CNAME 拷贝到静态文件夹并部署到 master 分支。如果只是在 GitHub 上设置(项目地址页面 -> Settings -> Options -> GitHub Pages -> Custom domain),它会自动添加到 master 分支上,但随后不包含 CNAME 的部署会将其覆盖。

    内容填写你的域名即可。

    About custom domains and GitHub Pages

    备案

    如果想要使用国内的一些服务,比如 CDN,不备案确实寸步难行。

    此处我指的是 ICP 备案,并非公安备案。(实际上我从来没有进行过公安备案,且目前在使用服务时,并未受到任何相关限制。)

    国内备案往往意味着你还需要一台国内的服务器,譬如通过腾讯云备案时会需要你设置关联的服务器(阿里云应当也是如此)。实际上你的网站并不一定得在这台服务器上,即便你只是免费试用了一个月,但是备案成功了,之后过期了对备案也不会有何影响。

    也就是说你完全可以使用学生优惠(10 元左右)购买一个月的云服务器,用于关联,并在这个月内抓紧备案好,此后云服务器过期不会影响备案问题。学生优惠的话 阿里云 或者 腾讯云 都有。

    备案前需要注意的几点就是:

    • 确定你的域名是否可以备案
    • 关闭评论区
    • 提交备案时的备注说明不得含有 交流 字样
    • 首页不能含有其他网站的直达链接
    • 遵纪守法无不良信息(这是当然的)

    你也可以直接关停网站,等待备案成功后再重新打开。(今后每年偶尔会复查,但相对会宽松许多。)

    此后,按照网站指引的备案步骤一步步来即可。(以前还要等待幕布寄送拍照,现在可以直接在手机上人脸验证)

    备案成功后页脚必须清晰地展示备案号,且备案号含有指向 http://www.beian.miit.gov.cn/ 的超链接。

    源文件备份

    备份什么?

    百密总有一疏,因此我们需要做好博客源文件的备份,你固然可以直接将整个文件夹打包,但当你后续安装的插件越来越多,你会发现压缩或者解压耗时越来越长,实际上我们只需要备份根目录的几个文件(夹)即可,source文件夹(里面存放着你博客的主要资源),_config.yml(HEXO 的配置,如果你不升级 HEXO 的话,这个也是很重要的),然后就是package.json(和它的名字一样,他能告诉你你安装了哪些插件及其对应的版本),有了这些你就能在另外一台电脑上很快恢复你的博客环境(当然我本人采用了Cloud Studio作为临时环境,也是不错的)

    我的package.json一览,如果其中一些插件你也有兴趣可以按照插件官方说明尝试,这里不做功能注释,虽然总会踩一些奇奇怪怪的坑,但当你慢慢修正时,虽然很折腾,但的确是乐在其中

    {
    "name": "hexo-site",
    "version": "0.0.0",
    "private": true,
    "scripts": {
    "build": "hexo generate",
    "clean": "hexo clean",
    "deploy": "hexo deploy",
    "server": "hexo server"
    },
    "hexo": {
    "version": "5.0.0"
    },
    "dependencies": {
    "cheerio": "^1.0.0-rc.3",
    "cnpm": "^6.1.1",
    "gulp-htmlmin": "^5.0.1",
    "hexo": "^5.0.0",
    "hexo-abbrlink": "^2.2.1",
    "hexo-baidu-url-submit": "0.0.6",
    "hexo-deployer-git": "^2.1.0",
    "hexo-feed": "^1.0.2",
    "hexo-generator-archive": "^1.0.0",
    "hexo-generator-baidu-sitemap": "^0.1.9",
    "hexo-generator-category": "^1.0.0",
    "hexo-generator-index": "^1.0.0",
    "hexo-generator-search": "^2.4.0",
    "hexo-generator-sitemap": "^2.1.0",
    "hexo-generator-tag": "^1.0.0",
    "hexo-render-pug": "^2.1.4",
    "hexo-renderer-ejs": "^1.0.0",
    "hexo-renderer-marked": "^3.0.0",
    "hexo-renderer-pug": "^1.0.0",
    "hexo-renderer-stylus": "^1.1.0",
    "hexo-server": "^1.0.0",
    "hexo-tag-aplayer": "^3.0.4",
    "hexo-wordcount": "^6.0.1",
    "imagemin": "^7.0.1",
    "npm-check": "^5.9.2",
    "terser": "^4.8.0"
    },
    "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-clean-css": "^4.3.0",
    "gulp-htmlclean": "^2.7.22",
    "gulp-imagemin": "^7.1.0",
    "gulp-uglify": "^3.0.2",
    "workbox-build": "^5.1.3"
    }
    }

    备份方式

    不能在一棵树上吊死,所以我选择了多平台备份,分别是 Github,Gitee,Coding 三个平台,多一个平台,多一份保障,这里注册账号实名认证什么的不再赘述,大家应该都会,注意的一点就是我们建的仓库选择**私有仓库**,不然别人把你 md 一拷走,就成别人的的了,不过大多数人比较自觉,我们这静态博客,F12 源码什么的也看的清清楚楚,爬走很简单,主要靠自觉,防止转载(其实无所谓,秉着开源共享的理念,其实标明出处大家也就不会特别在意)

    首先在博客根目录使用以下命令初始化本地仓库添加一个远程仓库

    git init

    如果本地未显示.git 文件夹,请注意打开显示隐藏文件夹

    然后运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写:

    git remote add <shortname> <url>

    比如 git remote add origin git@github.com:CCKNBC/Hexo.git,添加多个仓库地址等更多操作请参考Git-基础-远程仓库的使用,按照个人喜好来添加多个仓库地址,我这里全部使用的 origin,通过手动添加了 coding,gitee 的仓库地址,不影响使用就行

    然后我们运行git remote -v查看一下结果,是自己想要的即可

    origin  git@github.com:CCKNBC/Hexo.git (fetch)
    origin git@github.com:CCKNBC/Hexo.git (push)
    origin git@e.coding.net:ccknbc/blog/source.git (push)
    origin git@gitee.com:ccknbc/blog.git (push)

    然后我们就可以推送对应的内容了

    git pull
    git add .
    git commit -m "%date% %time%: Updated By CCKNBC Local"
    git push origin -u

    上面git push origin -u这个是因为第一次推送,我们采取强制推送,如果还是不行我们git push origin -f(因为是第一次无所谓,以后请不要随意使用-f),以后我们只需要git push即可,同时 commit 的内容请根据实际需要自行修改

    以下是我的.git/config一览,设置好后你可以更换你的第一个 url,也就是 fetch 仓库,根据个人喜好来(或者说网络原因),下面使用的是 github 的,那么 git pull 等操作就会按照这个仓库来和本地做比较,选择一个连接比较快的就好

    [core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
    [remote "origin"]
    url = git@github.com:CCKNBC/Hexo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@e.coding.net:ccknbc/blog/source.git
    url = git@gitee.com:ccknbc/blog.git
    [branch "master"]
    remote = origin
    merge = refs/heads/master

    在上面的添加多个仓库中,个人因为懒的输入命令,所以直接手动添加的下面两行,反正目的达到就行

    url = git@e.coding.net:ccknbc/blog/source.git
    url = git@gitee.com:ccknbc/blog.git

    然后在配置好公钥的情况下,强制推送即可,至此,你的博客源文件已经推送至你的备份仓库,可以去查看是否有一条强制推送的 commit 记录了,同时检查是否有theme文件夹(因为涉及到后面的魔改,部分源文件修改,因此我们也做好备份),如果没有,检查主题文件夹是否有.git文件夹,删掉后再次推送即可

    如何优雅的魔改

    在不动主题源文件方便日后升级的情况下,我们大部分采用外部引入 css,js 的方式实现,同时上传至 github,借用 jsDelivr 提供的 CDN 加速服务快速引用

    在博客根目录source文件夹下新建一个xxx.jsxxx.css,名字自己取就行,最后我们正确引入即可,在主题配置文件butterfly.yml(下文将直接简写根配(根目录的_confg.yml),主配(主题配置source目录下的 butterfly.yml))搜索 inject,然后在以下位置插入对应的 css 和 js 即可,例如,我是存放在主题文件夹子文件夹 css 和 js 内

    inject:
    head:
    - <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/CCKNBC/ccknbc.github.io@latest/css/ccknbc.css">
    bottom:
    - <script src="https://cdn.jsdelivr.net/gh/CCKNBC/ccknbc.github.io@latest/js/ccknbc.js"></script>

    所以按照上面所说的对应的你的链接即为,其中your name是你的 github 用户名,请注意根据具体路径变通

    https://cdn.jsdelivr.net/gh/your name/your name.github.io@latest/xxx.css
    https://cdn.jsdelivr.net/gh/your name/your namec.github.io@latests/xxx.js

    若是本地预览就可使用(请根据路径自己修改)

    /css/ccknbc.css
    /js/ccknbc.js

    接下来分别编辑 css 和 js 文件即可,当然你可以直接复制粘贴或者直接引用我的链接

    **css**

    @font-face {
    font-family: "sleek";
    src: url("https://cdn.jsdelivr.net/gh/lete114/CDN2/zaxiang/sleek.woff2");
    }

    /*标题颜色修改*/

    #page-header #site_title {
    color: #8fbc8f;
    }

    #page-header #site-name.blog_title {
    color: #8fbc8f;
    }

    /* 滚动条 */

    ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
    }

    ::-webkit-scrollbar-thumb {
    background-color: #8fbc8f;
    background-image: -webkit-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.4) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.4) 50%,
    rgba(255, 255, 255, 0.4) 75%,
    transparent 75%,
    transparent
    );
    border-radius: 2em;
    }

    ::-webkit-scrollbar-corner {
    background-color: transparent;
    }

    ::-moz-selection {
    color: #fff;
    background-color: #8fbc8f;
    }

    #web_bg {
    background: -webkit-linear-gradient(
    0deg,
    rgba(247, 149, 51, 0.1) 0,
    rgba(243, 112, 85, 0.1) 15%,
    rgba(239, 78, 123, 0.1) 30%,
    rgba(161, 102, 171, 0.1) 44%,
    rgba(80, 115, 184, 0.1) 58%,
    rgba(16, 152, 173, 0.1) 72%,
    rgba(7, 179, 155, 0.1) 86%,
    rgba(109, 186, 130, 0.1) 100%
    );
    background: -moz-linear-gradient(
    0deg,
    rgba(247, 149, 51, 0.1) 0,
    rgba(243, 112, 85, 0.1) 15%,
    rgba(239, 78, 123, 0.1) 30%,
    rgba(161, 102, 171, 0.1) 44%,
    rgba(80, 115, 184, 0.1) 58%,
    rgba(16, 152, 173, 0.1) 72%,
    rgba(7, 179, 155, 0.1) 86%,
    rgba(109, 186, 130, 0.1) 100%
    );
    background: -o-linear-gradient(
    0deg,
    rgba(247, 149, 51, 0.1) 0,
    rgba(243, 112, 85, 0.1) 15%,
    rgba(239, 78, 123, 0.1) 30%,
    rgba(161, 102, 171, 0.1) 44%,
    rgba(80, 115, 184, 0.1) 58%,
    rgba(16, 152, 173, 0.1) 72%,
    rgba(7, 179, 155, 0.1) 86%,
    rgba(109, 186, 130, 0.1) 100%
    );
    background: -ms-linear-gradient(
    0deg,
    rgba(247, 149, 51, 0.1) 0,
    rgba(243, 112, 85, 0.1) 15%,
    rgba(239, 78, 123, 0.1) 30%,
    rgba(161, 102, 171, 0.1) 44%,
    rgba(80, 115, 184, 0.1) 58%,
    rgba(16, 152, 173, 0.1) 72%,
    rgba(7, 179, 155, 0.1) 86%,
    rgba(109, 186, 130, 0.1) 100%
    );
    background: linear-gradient(
    90deg,
    rgba(247, 149, 51, 0.1) 0,
    rgba(243, 112, 85, 0.1) 15%,
    rgba(239, 78, 123, 0.1) 30%,
    rgba(161, 102, 171, 0.1) 44%,
    rgba(80, 115, 184, 0.1) 58%,
    rgba(16, 152, 173, 0.1) 72%,
    rgba(7, 179, 155, 0.1) 86%,
    rgba(109, 186, 130, 0.1) 100%
    );
    }

    .layout_post > #post {
    background: rgba(255, 255, 255, 0);
    }

    /* 鼠标图标 */

    body {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/Jkll8I.png), auto;
    }

    /*a标签*/

    a:hover {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    }

    /*按钮*/

    button:hover {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    }

    /*i标签*/

    i:hover {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    }

    /*页脚a标签*/

    /* #footer-wrap a:hover {
    text-decoration: none;
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    } */

    /*分页器*/

    #pagination .page-number:hover {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    }

    /*头部的导航栏*/

    #nav .site-page:hover {
    cursor: url(https://cdn.jsdelivr.net/gh/lete114/CDN@1.0/Use/JkuClT.png), auto;
    }

    /* a(链接)标签的默认颜色 */

    /* 宽度大于800小于9999执行 */

    /* @media only screen and (min-width: 800px) and (max-width: 9999px) {

    #article-container a {
    color: #00c4b6;
    display: inline-block;
    position: relative;
    }
    } */

    /* 打造效果渐变 */

    @-webkit-keyframes Gradient {
    0% {
    background-position: 0 50%;
    }
    50% {
    background-position: 100% 50%;
    }
    100% {
    background-position: 0 50%;
    }
    }

    @-moz-keyframes Gradient {
    0% {
    background-position: 0 50%;
    }
    50% {
    background-position: 100% 50%;
    }
    100% {
    background-position: 0 50%;
    }
    }

    @keyframes Gradient {
    0% {
    background-position: 0 50%;
    }
    50% {
    background-position: 100% 50%;
    }
    100% {
    background-position: 0 50%;
    }
    }

    #subtitle {
    background: linear-gradient(
    -45deg,
    #ffecd2,
    #fcb69f,
    #84fab0,
    #8fd3f4,
    #fddb92,
    #d1fdff,
    #e4afcb,
    #7edbdc,
    #eea2a2,
    #7ac5d8
    );
    background-size: 400% 400%;
    -webkit-animation: Gradient 10s ease infinite;
    -moz-animation: Gradient 10s ease infinite;
    animation: Gradient 10s ease infinite;
    -o-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
    }

    #subtitle:before {
    background-color: rgba(0, 0, 0, 0);
    }

    **js**

    // 设置页脚博主会动的心
    $(document).ready(function (e) {
    $(".copyright").html(
    '©2020 <i style="color:#49B1F5;animation: announ_animation 0.8s linear infinite;" class="fa fa-heartbeat"></i> CC康纳百川'
    );
    });

    if (aidaori()) {
    $("html").css({
    filter: "gray !important",
    filter: "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)",
    filter: "grayscale(100%)",
    "-webkit-filter": "grayscale(100%)",
    "-moz-filter": "grayscale(100%)",
    "-ms-filter": "grayscale(100%)",
    "-o-filter": "grayscale(100%)",
    });
    }
    //在特定日期变灰
    function aidaori() {
    var aidaoriarr = new Array(
    "0403",
    "0404",
    "0405",
    "0406",
    "0414",
    "0512",
    "0807",
    "0909",
    "1213"
    );
    //2020年4月4日 新冠肺炎哀悼日,清明节
    //2010年4月14日,青海玉树地震
    //2008年5月12日,四川汶川地震
    //2010年8月7日,甘肃舟曲特大泥石流
    //1976年9月9日,毛泽东逝世
    //1937年12月13日,南京大屠杀
    var mydate = new Date();
    var str = ""; // + mydate.getFullYear();
    var mm = mydate.getMonth() + 1;
    if (mydate.getMonth() > 9) {
    str += mm;
    } else {
    str += "0" + mm;
    }
    if (mydate.getDate() > 9) {
    str += mydate.getDate();
    } else {
    str += "0" + mydate.getDate();
    }
    if (aidaoriarr.indexOf(str) > -1) {
    return 1;
    } else {
    return 0;
    }
    }

    // 可爱的Title
    var OriginTitle = document.title;
    var titleTime;
    document.addEventListener("visibilitychange", function () {
    if (document.hidden) {
    $('[rel="icon"]').attr(
    "href",
    "https://cdn.jsdelivr.net/gh/CCKNBC/CDN/logo/ccknbc.png"
    );
    document.title = "(つェ⊂) 我藏好了哦~~";
    clearTimeout(titleTime);
    } else {
    $('[rel="icon"]').attr(
    "href",
    "https://cdn.jsdelivr.net/gh/CCKNBC/CDN/logo/favicon.svg"
    );
    document.title = "(*´∇`*) 被你发现啦~~" + OriginTitle;
    titleTime = setTimeout(function () {
    document.title = OriginTitle;
    }, 2000);
    }
    });

    更多类容可以百度,自己 DIY,有想法当然要实现啊


    未完待续…

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/hexo-toss/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/hexo-webpushr-notification/index.html b/posts/hexo-webpushr-notification/index.html new file mode 100644 index 000000000..95a17b5cb --- /dev/null +++ b/posts/hexo-webpushr-notification/index.html @@ -0,0 +1,19 @@ +Hexo浏览器定向推送文章更新 | CC的部落格

    Hexo浏览器定向推送文章更新

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    查看本文语雀版本【首发】,自动同步更新至CC 的部落格

    两年前,我刚开始使用Hexo的时候,写了一篇文章简单浏览器更新推送的实现,最近登录webpushr控制台,发现其支持按话题topic指定推送了,而原来的插件一直没有更新,且对个人的写作习惯不是很友好,所以对原插件进行了修改,并发布到了NPM

    欢迎大家前往订阅页面选择合适的订阅方式,关于邮件订阅,现已支持分类订阅

    安装

    推荐使用 npm 以插件形式安装

    npm i hexo-webpushr-notification

    自定义修改

    当然你也可以自定义修改webpushr.js文件后,再安装相关需要依赖,然后将文件放到Hexo/scripts/目录下即可正常运行,CC 本人亦是如此对于 0.2.0 以上版本,您只需要在 Hexo 所在目录安装 axios 即可,这样测试相较于安装 GitHub 更方便(以及欢迎 PR )

    npm i axios

    使用

    在你的 Hexo 根目录配置文件 _config.yml中添加如下内容,可按需配置,建议前往 README 查看最新配置

    webpushr:
    enable: true

    webpushrKey: "webpushrKey"
    webpushrAuthToken: "webpushrAuthToken"
    # 出于安全考虑,建议将上述两个重要参数添加至系统全局环境变量,并删除或注释掉此处配置
    # 否则可在网页端向访问者或订阅用户发送推送 https://www.webpushr.com/api-playground
    # 例如GitHub Actions环境变量配置,参数名不变,密钥名自定义,可参考如下
    # env:
    # webpushrKey: ${{ secrets.WEBPUSHR_KEY }}
    # webpushrAuthToken: ${{ secrets.WEBPUSHR_AUTH_TOKEN }}
    # 如果您的仓库私有,则无需担心此问题

    trackingCode: "trackingCode"
    icon: "https://.../192.png" # 必须为 HTTPS 以及 192*192 png图片
    # auto_hide: false # 默认为 1,代表true,即自动隐藏
    # sort: "date" # 默认为updated,即只要最新文章更改了更新时间即推送新文章,改为date即文章第一次发布时间
    # delay: "0" # 延时推送,考虑到CDN缓存更新,默认定时为在 hexo d 10分钟后推送,单位为分钟(最短延时为5分钟,设置 0 则会立即推送)
    # expire: "15d" # 推送过期时长,默认值为7天,格式如下:'5m'代表5分钟,'5h'代表5小时, '5d'代表5天.
    # image: # 默认为文章封面,Front-matter 属性为'cover'(butterfly主题友好选项),如果您没有定义默认封面或此属性,请在这里设置默认image
    action_buttons: # 如果你需要额外自定义按钮 可按照如下格式:
    - title: 阅读全文 # 当 title 未配置时 默认值为 “前往查看”
    # url: # 当 url 未配置时 默认值为 最新文章链接
    - title: 订阅页面
    url: https://blog.ccknbc.cc/sub/
    # 当 action_buttons 未定义时也默认保留了一个“前往查看”按钮,除非设置为 false
    # action_buttons: false # 当设为 false 则不显示额外的按钮,因为隐藏按钮即为当前文章链接

    # 以下配置为按订阅主题推送给不同订阅用户,请按照数组形式,一一对应,具体位置请看使用文档
    categories: [工作, 博客, 工具, 生活, 音乐, 学习]
    segment: ["484223", "484224", "484225", "484226", "484227", "484229"]
    endpoint: segment # 可选配置 all / segment / sid
    # 默认为 segment,即根据不同主题推送细分,同时配置上述选项
    # 例如 all,即推送至所有用户;针对本地测试,建议只推送给单个用户即自己,同时设置下方的 sid 值
    # 您也可以将segment 设置为 all-users 对应的ID,同样也可以实现推送至所有用户
    sid: "119810055" # 单个用户ID 可在控制台查看 https://app.webpushr.com/subscribers


    # 此外,在文章 Front-Matter 处
    # 可覆盖 auto_hide 和 expire 配置,针对需要特别提醒文章可以设置不自动隐藏及过期时间延长等操作
    # 以及可指定schedule参数(例如:schedule: 2022-10-01 00:00:00),定时推送
    # 当文章头设置 webpushr: false 时,可关闭本篇文章推送,此参数主要防止久远文章更改更新时间后自动推送
    1. 前往 webpushr 控制台获取如下参数,注册的时候可能会遇到一点困难,中国大陆用户需要科学上网来加载验证服务)
    2. 关于注册及一些具体内容,可以看之前的文章 简单浏览器更新推送的实现
    3. 依次点击 Integration > REST API Keys,即可看到你的webpushrKeywebpushrAuthToken
    4. 依次点击 Setup > TrackingCode,可以看到如下代码
    <!-- start webpushr tracking code -->
    <script>(function(w,d, s, id) {if(typeof(w.webpushr)!=='undefined') return;w.webpushr=w.webpushr||function(){(w.webpushr.q=w.webpushr.q||[]).push(arguments)};var js, fjs = d.getElementsByTagName(s)[0];js = d.createElement(s); js.id = id;js.async=1;js.src = "https://cdn.webpushr.com/app.min.js";
    fjs.parentNode.appendChild(js);}(window,document, 'script', 'webpushr-jssdk'));
    webpushr('setup',{'key':'BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58' });</script>
    <!-- end webpushr tracking code -->

    最后一行BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58 就是你的 trackingCode

    注意:因权限问题,本地测试时(hexo s)可能不会显示弹窗,但如果你配置了小铃铛,小铃铛会显示

    额外配置

    因官方 sw 脚本注册后,我们无法注册自己的 sw 脚本,但官方提供了配置,方便我们使用 sw 的缓存,拦截请求等功能

    首先在配置项中添加 sw_self: true配置,开启自行注册 sw(默认用户不用添加或者设为 false

    webpushr:
    sw_self: true

    另外,你还需要在你的脚本文件(例如sw.js)中引入

    importScripts('https://cdn.webpushr.com/sw-server.min.js');

    完成这些你就可以自行注册你的sw脚本了,如果你需要了解如何编写或注册service worker脚本,可以参考以下文章或项目 hexo-swpp
    Service Worker
    clientworker
    Workbox

    自定义

    个人建议将控制台右上角小铃铛 🔔 里全部配置一遍以获得更好的效果

    你需要自定义一些参数才可以使用根据不同主题,按照订阅者订阅话题推送功能(目前根据个人需求是这个设置,默认行为为当未匹配到对应分类时不推送文章,而不是向所有用户推送文章,当然你也可以配置目标为所有用户)

    在控制台,点击Setup>Opt-In Prompt ,向下滑动打开Enable Topics(小铃铛样式无此选项,因此推荐您使用前两种样式),并新增几个主题,对应你想推送的文章分类即可

    然后点击Users>Segments ,即可获取对应的segment关系,依次填入配置项即可

    工作原理

    当你运行hexo generate插件会在public 目录生成 newPost.json 这样一个文件. newPost.json 包含了一些你想推送的新文章相关信息,示例格式如下

    {
    "title": "Hexo浏览器定向推送文章更新",
    "updated": "2023-04-22T20:25:00+08:00",
    "message": "这一次,CC的部落格可以根据读者订阅主题定向推送了,并且实现了NPM插件化",
    "target_url": "https://blog.ccknbc.cc/posts/hexo-webpushr-notification/",
    "image": "https://pic1.afdiancdn.com/user/8a7f563c2e3811ecab5852540025c377/common/d2a947d48815ed24936a919873b97841_w1366_h768_s31.png",
    "categories": ["博客"],
    "schedule": "2023-06-13T15:16:41.187Z",
    "expire": "7d",
    "auto_hide": "1"
    }

    而他的来源就是我们在文章开头Front-Matter自定义的那些属性,而本插件针对Butterfly主题做了针对性修改,您也可以在您的模板文件目录下修改文章模板文件(Hexo/scaffolds/post.md),主要针对性参数如下

    date:
    updated:
    schedule: 对应配置项中定时推送时间
    auto_hide: 对应配置项中是否自动隐藏
    expire: 对应配置项中过期时间
    categories: 文章分类
    description: 对应配置项中message,即文章描述
    cover: 对应配置项中image,默认选取文章封面

    如果你的主题不是采用默认的date updated 参数,记得补充,因为这是判断最新文章的依据

    如果你习惯了使用截断的方式,也无需配置description继续使用,示例如下,注意<!-- more -->

    ---
    title: Hexo使用Web Push Notification 浏览器通知推送
    tags:
    - hexo
    - 服务器推送技术
    - push notifications
    categories:
    - 开发
    comments: true
    abbrlink: 98ae9e55
    date: 2020-02-26 10:00:00
    ---

    Web Push Notification 是怎么工作的?个人博客为什么要使用它?如何使用它?

    <!-- more -->

    当执行 hexo deploy命令时,插件会比较在线版本和本地版本newPost.json中最新文章更新时间是否一致,如果不同,则插件将推送最新文章更新通知(默认为十分钟后推送)

    注意:如果您是第一次使用本地测试应该看到

    INFO  无文章更新 或 为首次推送更新

    这是正常现象,因为此时你的网站还没有newPost.json这个文件,后续有更新时将正常推送,你可以先推送一次,再修改更新时间测试一次,当然建议测试目标选择自己,即 sid 选项配置

    当然如果您在使用过程中有什么问题或遇到了 Bug 也欢迎随时在评论区或issues反馈,当然因为本人是菜鸡,所以有大佬 PR 最好了

    推送效果

    因为我是通知自动隐藏后才截图,所以大致效果如下所示

    后续计划

    • 兼容自定义Service Work的功能,因为webpushr-sw.js优先注册的原因,只能有一个 sw注册,无法注册自己编写脚本。
    • 支持参数更多的可自定义,启用或关闭。例如不延时,立即发送;不显示按钮(因为默认就是跳转到文章)等
    • 目前的判断逻辑,虽然可以根据更新时间来判断,但如果很久之前的文章翻新,只要更新时间最新,也会触发推送,主要针对 updated 方式,还没想到好的解决办法,目前就是确认需要推送才更改更新时间咯
    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/hexo-webpushr-notification/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/how-to-ask-questions-the-smart-way/index.html b/posts/how-to-ask-questions-the-smart-way/index.html new file mode 100644 index 000000000..8ae71b81e --- /dev/null +++ b/posts/how-to-ask-questions-the-smart-way/index.html @@ -0,0 +1,19 @@ +提问的智慧 | CC的部落格

    提问的智慧

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀 自动同步更新至CC 的部落格

    提问的智慧

    How To Ask Questions The Smart Way

    Copyright © 2001, 2006, 2014 Eric S. Raymond, Rick Moen

    本指南英文版版权为 Eric S. Raymond, Rick Moen 所有。

    原文网址:http://www.catb.org/~esr/faqs/smart-questions.html

    Copyleft 2001 by D.H.Grand(nOBODY/Ginux), 2010 by Gasolin, 2015 by Ryan Wu

    本中文指南是基于原文 3.10 版以及 2010 年由 Gasolin 所翻译版本的最新翻译;

    协助指出翻译问题,请发 Issue,或直接发 Pull Request 给我。

    本文另有繁體中文版(若在本站查看,可使用右下角简繁转换按钮)。

    原文版本历史

    目录

    声明

    许多项目在他们的使用协助/说明网页中链接了本指南,这么做很好,我们也鼓励大家都这么做。但如果你是负责管理这个项目网页的人,请在超链接附近的显著位置上注明:

    本指南不提供此项目的实际支持服务!

    我们已经深刻领教到少了上述声明所带来的痛苦。因为少了这点声明,我们不停地被一些白痴纠缠。这些白痴认为既然我们发布了这本指南,那么我们就有责任解决世上所有的技术问题。

    如果你是因为需要某些协助而正在阅读这本指南,并且最后离开是因为发现从本指南作者们身上得不到直接的协助,那么你就是我们所说的那些白痴之一。别问我们问题,我们只会忽略你。我们在这本指南中是教你如何从那些真正懂得你所遇到软件或硬件问题的人取得协助,而 99% 的情况下那不会是我们。除非你确定本指南的作者之一刚好是你所遇到的问题领域的专家,否则请不要打扰我们,这样大家都会开心一点。

    简介

    在黑客的世界里,当你拋出一个技术问题时,最终是否能得到有用的回答,往往取决于你所提问和追问的方式。本指南将教你如何正确的提问以获得你满意的答案。

    不只是黑客,现在开源(Open Source)软件已经相当盛行,你常常也可以由其他有经验的使用者身上得到好答案,这是件好事;使用者比起黑客来,往往对那些新手常遇到的问题更宽容一些。然而,将有经验的使用者视为黑客,并采用本指南所提的方法与他们沟通,同样也是能从他们身上得到满意回答的最有效方式。

    首先你应该明白,黑客们喜爱有挑战性的问题,或者能激发他们思维的好问题。如果我们并非如此,那我们也不会成为你想询问的对象。如果你给了我们一个值得反复咀嚼玩味的好问题,我们自会对你感激不尽。好问题是激励,是厚礼。好问题可以提高我们的理解力,而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言,"好问题!"是诚挚的大力称赞。

    尽管如此,黑客们有着蔑视或傲慢面对简单问题的坏名声,这有时让我们看起来对新手、无知者似乎较有敌意,但其实不是那样的。

    我们不讳言我们对那些不愿思考、或者在发问前不做他们该做的事的人的蔑视。那些人是时间杀手 —— 他们只想索取,从不付出,消耗我们可用在更有趣的问题或更值得回答的人身上的时间。我们称这样的人为 失败者(撸瑟) (由于历史原因,我们有时把它拼作 lusers)。

    我们意识到许多人只是想使用我们写的软件,他们对学习技术细节没有兴趣。对大多数人而言,电脑只是种工具,是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做。我们了解这点,也从不指望每个人都对这些让我们着迷的技术问题感兴趣。尽管如此,我们回答问题的风格是指向那些真正对此有兴趣并愿意主动参与解决问题的人,这一点不会变,也不该变。如果连这都变了,我们就是在降低做自己最擅长的事情上的效率。

    我们(在很大程度上)是自愿的,从繁忙的生活中抽出时间来解答疑惑,而且时常被提问淹没。所以我们无情的滤掉一些话题,特别是拋弃那些看起来像失败者的家伙,以便更高效的利用时间来回答赢家(winner)的问题。

    如果你厌恶我们的态度,高高在上,或过于傲慢,不妨也设身处地想想。我们并没有要求你向我们屈服 —— 事实上,我们大多数人非常乐意与你平等地交流,只要你付出小小努力来满足基本要求,我们就会欢迎你加入我们的文化。但让我们帮助那些不愿意帮助自己的人是没有效率的。无知没有关系,但装白痴就是不行。

    所以,你不必在技术上很在行才能吸引我们的注意,但你必须表现出能引导你变得在行的特质 —— 机敏、有想法、善于观察、乐于主动参与解决问题。如果你做不到这些使你与众不同的事情,我们建议你花点钱找家商业公司签个技术支持服务合同,而不是要求黑客个人无偿地帮助你。

    如果你决定向我们求助,当然你也不希望被视为失败者,更不愿成为失败者中的一员。能立刻得到快速并有效答案的最好方法,就是像赢家那样提问 —— 聪明、自信、有解决问题的思路,只是偶尔在特定的问题上需要获得一点帮助。

    (欢迎对本指南提出改进意见。你可以 email 你的建议至 esr@thyrsus.comrespond-auto@linuxmafia.com。然而请注意,本文并非网络礼节的通用指南,而我们通常会拒绝无助于在技术论坛得到有用答案的建议)。

    在提问之前

    在你准备要通过电子邮件、新闻群组或者聊天室提出技术问题前,请先做到以下事情:

    1. 尝试在你准备提问的论坛的旧文章中搜索答案。
    2. 尝试上网搜索以找到答案。
    3. 尝试阅读手册以找到答案。
    4. 尝试阅读常见问题文件(FAQ)以找到答案。
    5. 尝试自己检查或试验以找到答案。
    6. 向你身边的强者朋友打听以找到答案。
    7. 如果你是程序开发者,请尝试阅读源代码以找到答案。

    当你提出问题的时候,请先表明你已经做了上述的努力;这将有助于树立你并不是一个不劳而获且浪费别人的时间的提问者。如果你能一并表达在做了上述努力的过程中所学到的东西会更好,因为我们更乐于回答那些表现出能从答案中学习的人的问题。

    运用某些策略,比如先用 Google 搜索你所遇到的各种错误信息(搜索 Google 论坛和网页),这样很可能直接就找到了能解决问题的文件或邮件列表线索。即使没有结果,在邮件列表或新闻组寻求帮助时加上一句 我在 Google 中搜过下列句子但没有找到什么有用的东西 也是件好事,即使它只是表明了搜索引擎不能提供哪些帮助。这么做(加上搜索过的字串)也让遇到相似问题的其他人能被搜索引擎引导到你的提问来。

    别着急,不要指望几秒钟的 Google 搜索就能解决一个复杂的问题。在向专家求助之前,再阅读一下常见问题文件(FAQ)、放轻松、坐舒服一些,再花点时间思考一下这个问题。相信我们,他们能从你的提问看出你做了多少阅读与思考,如果你是有备而来,将更有可能得到解答。不要将所有问题一股脑拋出,只因你的第一次搜索没有找到答案(或者找到太多答案)。

    准备好你的问题,再将问题仔细的思考过一遍,因为草率的发问只能得到草率的回答,或者根本得不到任何答案。越是能表现出在寻求帮助前你为解决问题所付出的努力,你越有可能得到实质性的帮助。

    小心别问错了问题。如果你的问题基于错误的假设,某个普通黑客(J. Random Hacker)多半会一边在心里想着蠢问题…, 一边用无意义的字面解释来答复你,希望着你会从问题的回答(而非你想得到的答案)中汲取教训。

    绝不要自以为够格得到答案,你没有;你并没有。毕竟你没有为这种服务支付任何报酬。你将会是自己去挣到一个答案,靠提出有内涵的、有趣的、有思维激励作用的问题 —— 一个有潜力能贡献社区经验的问题,而不仅仅是被动的从他人处索取知识。

    另一方面,表明你愿意在找答案的过程中做点什么是一个非常好的开端。谁能给点提示?、我的这个例子里缺了什么?以及我应该检查什么地方比请把我需要的确切的过程贴出来更容易得到答复。因为你表现出只要有人能指个正确方向,你就有完成它的能力和决心。

    当你提问时

    慎选提问的论坛

    小心选择你要提问的场合。如果你做了下述的事情,你很可能被忽略掉或者被看作失败者:

    • 在与主题不合的论坛上贴出你的问题。
    • 在探讨进阶技术问题的论坛张贴非常初级的问题;反之亦然。
    • 在太多的不同新闻群组上重复转贴同样的问题(cross-post)。
    • 向既非熟人也没有义务解决你问题的人发送私人电邮。

    黑客会剔除掉那些搞错场合的问题,以保护他们沟通的渠道不被无关的东西淹没。你不会想让这种事发生在自己身上的。

    因此,第一步是找到对的论坛。再说一次,Google 和其它搜索引擎还是你的朋友,用它们来找到与你遭遇到困难的软硬件问题最相关的网站。通常那儿都有常见问题(FAQ)、邮件列表及相关说明文件的链接。如果你的努力(包括阅读 FAQ)都没有结果,网站上也许还有报告 Bug(Bug-reporting)的流程或链接,如果是这样,链过去看看。

    向陌生的人或论坛发送邮件最可能是风险最大的事情。举例来说,别假设一个提供丰富内容的网页的作者会想充当你的免费顾问。不要对你的问题是否会受到欢迎做太乐观的估计 —— 如果你不确定,那就向别处发送,或者压根别发。

    在选择论坛、新闻群组或邮件列表时,别太相信名字,先看看 FAQ 或者许可书以弄清楚你的问题是否切题。发文前先翻翻已有的话题,这样可以让你感受一下那里的文化。事实上,事先在新闻组或邮件列表的历史记录中搜索与你问题相关的关键词是个极好的主意,也许这样就找到答案了。即使没有,也能帮助你归纳出更好的问题。

    别像机关枪似的一次"扫射"所有的帮助渠道,这就像大喊大叫一样会使人不快。要一个一个地来。

    搞清楚你的主题!最典型的错误之一是在某种致力于跨平台可移植的语言、套件或工具的论坛中提关于 Unix 或 Windows 操作系统程序界面的问题。如果你不明白为什么这是大错,最好在搞清楚这之间差异之前什么也别问。

    一般来说,在仔细挑选的公共论坛中提问,会比在私有论坛中提同样的问题更容易得到有用的回答。有几个理由可以支持这点,一是看潜在的回复者有多少,二是看观众有多少。黑客较愿意回答那些能帮助到许多人的问题。

    可以理解的是,老练的黑客和一些热门软件的作者正在接受过多的错发信息。就像那根最后压垮骆驼背的稻草一样,你的加入也有可能使情况走向极端 —— 已经好几次了,一些热门软件的作者从自己软件的支持中抽身出来,因为伴随而来涌入其私人邮箱的无用邮件变得无法忍受。

    Stack Overflow

    搜索,然后 在 Stack Exchange 问。

    近年来,Stack Exchange community 社区已经成为回答技术及其他问题的主要渠道,尤其是那些开放源码的项目。

    因为 Google 索引是即时的,在看 Stack Exchange 之前先在 Google 搜索。有很高的机率某人已经问了一个类似的问题,而且 Stack Exchange 网站们往往会是搜索结果中最前面几个。如果你在 Google 上没有找到任何答案,你再到特定相关主题的网站去找。用标签(Tag)搜索能让你更缩小你的搜索结果。

    Stack Exchange 已经成长到超过一百个网站,以下是最常用的几个站:

    • Super User 是问一些通用的电脑问题,如果你的问题跟代码或是写程序无关,只是一些网络连线之类的,请到这里。
    • Stack Overflow 是问写程序有关的问题。
    • Server Fault 是问服务器和网管相关的问题。

    网站和 IRC 论坛

    本地的使用者群组(user group),或者你所用的 Linux 发行版本也许正在宣传他们的网页论坛或 IRC 频道,并提供新手帮助(在一些非英语国家,新手论坛很可能还是邮件列表), 这些地方是开始提问的好首选,特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。有广告赞助的 IRC 频道是公开欢迎提问的地方,通常可以即时得到回应。

    事实上,如果程序出的问题只发生在特定 Linux 发行版提供的版本(这很常见),最好先去该发行版的论坛或邮件列表中提问,再到程序本身的论坛或邮件列表提问。(否则)该项目的黑客可能仅仅回复 “用我们的版本”。

    在任何论坛发文以前,先确认一下有没有搜索功能。如果有,就试着搜索一下问题的几个关键词,也许这会有帮助。如果在此之前你已做过通用的网页搜索(你也该这样做),还是再搜索一下论坛,搜索引擎有可能没来得及索引此论坛的全部内容。

    通过论坛或 IRC 频道来提供使用者支持服务有增长的趋势,电子邮件则大多为项目开发者间的交流而保留。所以最好先在论坛或 IRC 中寻求与该项目相关的协助。

    在使用 IRC 的时候,首先最好不要发布很长的问题描述,有些人称之为频道洪水。最好通过一句话的问题描述来开始聊天。

    第二步,使用项目邮件列表

    当某个项目提供开发者邮件列表时,要向列表而不是其中的个别成员提问,即使你确信他能最好地回答你的问题。查一查项目的文件和首页,找到项目的邮件列表并使用它。有几个很好的理由支持我们采用这种办法:

    • 任何好到需要向个别开发者提出的问题,也将对整个项目群组有益。反之,如果你认为自己的问题对整个项目群组来说太愚蠢,也不能成为骚扰个别开发者的理由。
    • 向列表提问可以分散开发者的负担,个别开发者(尤其是项目领导人)也许太忙以至于没法回答你的问题。
    • 大多数邮件列表都会被存档,那些被存档的内容将被搜索引擎索引。如果你向列表提问并得到解答,将来其它人可以通过网页搜索找到你的问题和答案,也就不用再次发问了。
    • 如果某些问题经常被问到,开发者可以利用此信息来改进说明文件或软件本身,以使其更清楚。如果只是私下提问,就没有人能看到最常见问题的完整场景。

    如果一个项目既有"使用者" 也有"开发者"(或"黑客")邮件列表或论坛,而你又不会动到那些源代码,那么就向"使用者"列表或论坛提问。不要假设自己会在开发者列表中受到欢迎,那些人多半会将你的提问视为干扰他们开发的噪音。

    然而,如果你确信你的问题很特别,而且在"使用者" 列表或论坛中几天都没有回复,可以试试前往"开发者"列表或论坛发问。建议你在张贴前最好先暗地里观察几天以了解那里的行事方式(事实上这是参与任何私有或半私有列表的好主意)

    如果你找不到一个项目的邮件列表,而只能查到项目维护者的电子邮件地址,尽管向他发信。即使是在这种情况下,也别假设(项目)邮件列表不存在。在你的电子邮件中,请陈述你已经试过但没有找到合适的邮件列表,也提及你不反对将自己的邮件转发给他人(许多人认为,即使没什么秘密,私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人,你给了相应人员处置你邮件的选择)。

    使用有意义且描述明确的标题

    在邮件列表、新闻群组或论坛中,大约 50 字以内的标题是抓住资深专家注意力的好机会。别用喋喋不休的帮帮忙、跪求、急(更别说救命啊!!! 这样让人反感的话,用这种标题会被条件反射式地忽略)来浪费这个机会。不要妄想用你的痛苦程度来打动我们,而应该是在这点空间中使用极简单扼要的描述方式来提出问题。

    一个好标题范例是目标 —— 差异式的描述,许多技术支持组织就是这样做的。在目标部分指出是哪一个或哪一组东西有问题,在差异部分则描述与期望的行为不一致的地方。

    蠢问题:救命啊!我的笔记本电脑不能正常显示了!

    聪明问题:X.org 6.8.1 的鼠标光标会变形,某牌显卡 MV1005 芯片组。

    更聪明问题:X.org 6.8.1 的鼠标光标,在某牌显卡 MV1005 芯片组环境下 - 会变形。

    编写目标 —— 差异 式描述的过程有助于你组织对问题的细致思考。是什么被影响了? 仅仅是鼠标光标或者还有其它图形?只在 X.org 的 X 版中出现?或只是出现在 6.8.1 版中? 是针对某牌显卡芯片组?或者只是其中的 MV1005 型号? 一个黑客只需瞄一眼就能够立即明白你的环境和你遇到的问题。

    总而言之,请想像一下你正在一个只显示标题的存档讨论串(Thread)索引中查寻。让你的标题更好地反映问题,可使下一个搜索类似问题的人能够关注这个讨论串,而不用再次提问相同的问题。

    如果你想在回复中提出问题,记得要修改内容标题,以表明你是在问一个问题, 一个看起来像 Re: 测试 或者 Re: 新 bug 的标题很难引起足够重视。另外,在不影响连贯性之下,适当引用并删减前文的内容,能给新来的读者留下线索。

    对于讨论串,不要直接点击回复来开始一个全新的讨论串,这将限制你的观众。因为有些邮件阅读程序,比如 mutt ,允许使用者按讨论串排序并通过折叠讨论串来隐藏消息,这样做的人永远看不到你发的消息。

    仅仅改变标题还不够。mutt 和其它一些邮件阅读程序还会检查邮件标题以外的其它信息,以便为其指定讨论串。所以宁可发一个全新的邮件。

    在网页论坛上,好的提问方式稍有不同,因为讨论串与特定的信息紧密结合,并且通常在讨论串外就看不到里面的内容,故通过回复提问,而非改变标题是可接受的。不是所有论坛都允许在回复中出现分离的标题,而且这样做了基本上没有人会去看。不过,通过回复提问,这本身就是暧昧的做法,因为它们只会被正在查看该标题的人读到。所以,除非你只想在该讨论串当前活跃的人群中提问,不然还是另起炉灶比较好。

    使问题容易回复

    以请将你的回复发送到……来结束你的问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦,我们也觉得花几秒钟思考你的问题更麻烦。如果你的邮件程序不支持这样做,换个好点的;如果是操作系统不支持这种邮件程序,也换个好点的。

    在论坛,要求通过电子邮件回复是非常无礼的,除非你认为回复的信息可能比较敏感(有人会为了某些未知的原因,只让你而不是整个论坛知道答案)。如果你只是想在有人回复讨论串时得到电子邮件提醒,可以要求网页论坛发送给你。几乎所有论坛都支持诸如追踪此讨论串、有回复时发送邮件提醒等功能。

    用清晰、正确、精准且语法正确的语句

    我们从经验中发现,粗心的提问者通常也会粗心的写程序与思考(我敢打包票)。回答粗心大意者的问题很不值得,我们宁愿把时间耗在别处。

    正确的拼写、标点符号和大小写是很重要的。一般来说,如果你觉得这样做很麻烦,不想在乎这些,那我们也觉得麻烦,不想在乎你的提问。花点额外的精力斟酌一下字句,用不着太僵硬与正式 —— 事实上,黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它必须很准确,而且有迹象表明你是在思考和关注问题。

    正确地拼写、使用标点和大小写,不要将 its 混淆为 it’s,loose 搞成 lose 或者将 discrete 弄成 discreet。不要全部用大写,这会被视为无礼的大声嚷嚷(全部小写也好不到哪去,因为不易阅读。Alan Cox 也许可以这样做,但你不行)。

    更白话的说,如果你写得像是个半文盲 [译注:小白],那多半得不到理睬。也不要使用即时通信中的简写或火星文,如将的简化为 d 会使你看起来像一个为了少打几个键而省字的小白。更糟的是,如果像个小孩似地鬼画符那绝对是在找死,可以肯定没人会理你(或者最多是给你一大堆指责与挖苦)。

    如果在使用非母语的论坛提问,你可以犯点拼写和语法上的小错,但决不能在思考上马虎(没错,我们通常能弄清两者的分别)。同时,除非你知道回复者使用的语言,否则请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂语言写的消息。在网络上英语是通用语言,用英语书写可以将你的问题在尚未被阅读就被直接删除的可能性降到最低。

    如果英文是你的外语(Second language),提示潜在回复者你有潜在的语言困难是很好的: [译注:以下附上原文以供使用]

    English is not my native language; please excuse typing errors.

    • 英文不是我的母语,请原谅我的错字或语法。

    If you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.

    • 如果你说某语言,请寄信/私讯给我;我需要有人协助我翻译我的问题。

    I am familiar with the technical terms, but some slang expressions and idioms are difficult for me.

    • 我对技术名词很熟悉,但对于俗语或是特别用法比较不甚了解。

    I’ve posted my question in $LANGUAGE and English. I’ll be glad to translate responses, if you only use one or the other.

    • 我把我的问题用某语言和英文写出来,如果你只用一种语言回答,我会乐意将其翻译成另一种。

    使用易于读取且标准的文件格式发送问题

    如果你人为地将问题搞得难以阅读,它多半会被忽略,人们更愿读易懂的问题,所以:

    • 使用纯文字而不是 HTML (关闭 HTML 并不难)。
    • 使用 MIME 附件通常是可以的,前提是真正有内容(譬如附带的源代码或 patch),而不仅仅是邮件程序生成的模板(譬如只是信件内容的拷贝)。
    • 不要发送一段文字只是一行句子但自动换行后会变成多行的邮件(这使得回复部分内容非常困难)。设想你的读者是在 80 个字符宽的终端机上阅读邮件,最好设置你的换行分割点小于 80 字。
    • 但是,对一些特殊的文件不要设置固定宽度(譬如日志档案拷贝或会话记录)。数据应该原样包含,让回复者有信心他们看到的是和你看到的一样的东西。
    • 在英语论坛中,不要使用Quoted-Printable MIME 编码发送消息。这种编码对于张贴非 ASCII 语言可能是必须的,但很多邮件程序并不支持这种编码。当它们处理换行时,那些文本中四处散布的=20符号既难看也分散注意力,甚至有可能破坏内容的语意。
    • 绝对,永远不要指望黑客们阅读使用封闭格式编写的文档,像微软公司的 Word 或 Excel 文件等。大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你家门口时你的反应一样。即便他们能够处理,他们也很厌恶这么做。
    • 如果你从使用 Windows 的电脑发送电子邮件,关闭微软愚蠢的智能引号功能 (从[选项] > [校订] > [自动校正选项],勾选掉智能引号单选框),以免在你的邮件中到处散布垃圾字符。
    • 在论坛,勿滥用表情符号HTML功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。这通常不是个好主意,除非你只是对性而不是对答案感兴趣。

    如果你使用图形用户界面的邮件程序(如微软公司的 Outlook 或者其它类似的),注意它们的默认设置不一定满足这些要求。大多数这类程序有基于选单的查看源代码命令,用它来检查发送文件夹中的邮件,以确保发送的是纯文本文件同时没有一些奇怪的字符。

    精确地描述问题并言之有物

    • 仔细、清楚地描述你的问题或 Bug 的症状。
    • 描述问题发生的环境(机器配置、操作系统、应用程序、以及相关的信息),提供经销商的发行版和版本号(如:Fedora Core 4Slackware 9.1等)。
    • 描述在提问前你是怎样去研究和理解这个问题的。
    • 描述在提问前为确定问题而采取的诊断步骤。
    • 描述最近做过什么可能相关的硬件或软件变更。
    • 尽可能的提供一个可以重现这个问题的可控环境的方法。

    尽量去揣测一个黑客会怎样反问你,在你提问之前预先将黑客们可能遇到的问题回答一遍。

    以上几点中,当你报告的是你认为可能在代码中的问题时,给黑客一个可以重现你的问题的环境尤其重要。当你这么做时,你得到有效的回答的机会和速度都会大大的提升。

    Simon Tatham 写过一篇名为《如何有效的报告 Bug》的出色文章。强力推荐你也读一读。

    话不在多而在精

    你需要提供精确有内容的信息。这并不是要求你简单的把成堆的出错代码或者资料完全转录到你的提问中。如果你有庞大而复杂的测试样例能重现程序挂掉的情境,尽量将它剪裁得越小越好。

    这样做的用处至少有三点。第一,表现出你为简化问题付出了努力,这可以使你得到回答的机会增加;第二,简化问题使你更有可能得到有用的答案;第三,在精炼你的 bug 报告的过程中,你很可能就自己找到了解决方法或权宜之计。

    别动辄声称找到 Bug

    当你在使用软件中遇到问题,除非你非常、非常的有根据,不要动辄声称找到了 Bug。提示:除非你能提供解决问题的源代码补丁,或者提供回归测试来表明前一版本中行为不正确,否则你都多半不够完全确信。这同样适用在网页和文件,如果你(声称)发现了文件的 Bug,你应该能提供相应位置的修正或替代文件。

    请记得,还有许多其它使用者没遇到你发现的问题,否则你在阅读文件或搜索网页时就应该发现了(你在抱怨前已经做了这些,是吧?)。这也意味着很有可能是你弄错了而不是软件本身有问题。

    编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了 Bug,也就是在质疑他们的能力,即使你是对的,也有可能会冒犯到其中某部分人。当你在标题中嚷嚷着有 Bug 时,这尤其严重。

    提问时,即使你私下非常确信已经发现一个真正的 Bug,最好写得像是你做错了什么。如果真的有 Bug,你会在回复中看到这点。这样做的话,如果真有 Bug,维护者就会向你道歉,这总比你惹恼别人然后欠别人一个道歉要好一点。

    低声下气不能代替你的功课

    有些人明白他们不该粗鲁或傲慢的提问并要求得到答复,但他们选择另一个极端 —— 低声下气:我知道我只是个可悲的新手,一个撸瑟,但… 这既使人困扰,也没有用,尤其是伴随着与实际问题含糊不清的描述时更令人反感。

    别用原始灵长类动物的把戏来浪费你我的时间。取而代之的是,尽可能清楚地描述背景条件和你的问题情况。这比低声下气更好地定位了你的位置。

    有时网页论坛会设有专为新手提问的版面,如果你真的认为遇到了初学者的问题,到那去就是了,但一样别那么低声下气。

    描述问题症状而非你的猜测

    告诉黑客们你认为问题是怎样造成的并没什么帮助。(如果你的推断如此有效,还用向别人求助吗?),因此要确信你原原本本告诉了他们问题的症状,而不是你的解释和理论;让黑客们来推测和诊断。如果你认为陈述自己的猜测很重要,清楚地说明这只是你的猜测,并描述为什么它们不起作用。

    蠢问题

    我在编译内核时接连遇到 SIG11 错误,我怀疑某条飞线搭在主板的走线上了,这种情况应该怎样检查最好?

    聪明问题

    我的组装电脑是 FIC-PA2007 主机板搭载 AMD K6/233 CPU(威盛 Apollo VP2 芯片组), 256MB Corsair PC133 SDRAM 内存,在编译内核时,从开机 20 分钟以后就频频产生 SIG11 错误,但是在头 20 分钟内从没发生过相同的问题。重新启动也没有用,但是关机一晚上就又能工作 20 分钟。所有内存都换过了,没有效果。相关部分的标准编译记录如下…。

    由于以上这点似乎让许多人觉得难以配合,这里有句话可以提醒你:所有的诊断专家都来自密苏里州。 美国国务院的官方座右铭则是:让我看看(出自国会议员 Willard D. Vandiver 在 1899 年时的讲话:我来自一个出产玉米,棉花,牛蒡和民主党人的国家,滔滔雄辩既不能说服我,也不会让我满意。我来自密苏里州,你必须让我看看。) 针对诊断者而言,这并不是一种怀疑,而只是一种真实而有用的需求,以便让他们看到的是与你看到的原始证据尽可能一致的东西,而不是你的猜测与归纳的结论。所以,大方的展示给我们看吧!

    按发生时间先后列出问题症状

    问题发生前的一系列操作,往往就是对找出问题最有帮助的线索。因此,你的说明里应该包含你的操作步骤,以及机器和软件的反应,直到问题发生。在命令行处理的情况下,提供一段操作记录(例如运行脚本工具所生成的),并引用相关的若干行(如 20 行)记录会非常有帮助。

    如果挂掉的程序有诊断选项(如 -v 的详述开关),试着选择这些能在记录中增加调试信息的选项。记住,多不等于好。试着选取适当的调试级别以便提供有用的信息而不是让读者淹没在垃圾中。

    如果你的说明很长(如超过四个段落),在开头简述问题,接下来再按时间顺序详述会有所帮助。这样黑客们在读你的记录时就知道该注意哪些内容了。

    描述目标而不是过程

    如果你想弄清楚如何做某事(而不是报告一个 Bug),在开头就描述你的目标,然后才陈述重现你所卡住的特定步骤。

    经常寻求技术帮助的人在心中有个更高层次的目标,而他们在自以为能达到目标的特定道路上被卡住了,然后跑来问该怎么走,但没有意识到这条路本身就有问题。结果要费很大的劲才能搞定。

    蠢问题

    我怎样才能从某绘图程序的颜色选择器中取得十六进制的的 RGB 值?

    聪明问题

    我正试着用替换一幅图片的色码(color table)成自己选定的色码,我现在知道的唯一方法是编辑每个色码区块(table slot),但却无法从某绘图程序的颜色选择器取得十六进制的的 RGB 值。

    第二种提问法比较聪明,你可能得到像是建议采用另一个更合适的工具的回复。

    别要求使用私人电邮回复

    黑客们认为问题的解决过程应该公开、透明,此过程中如果更有经验的人注意到不完整或者不当之处,最初的回复才能够、也应该被纠正。同时,作为提供帮助者可以得到一些奖励,奖励就是他的能力和学识被其他同行看到。

    当你要求私下回复时,这个过程和奖励都被中止。别这样做,让回复者来决定是否私下回答 —— 如果他真这么做了,通常是因为他认为问题编写太差或者太肤浅,以至于对其它人没有兴趣。

    这条规则存在一条有限的例外,如果你确信提问可能会引来大量雷同的回复时,那么这个神奇的提问句会是向我发电邮,我将为论坛归纳这些回复。试着将邮件列表或新闻群组从洪水般的雷同回复中解救出来是非常有礼貌的 —— 但你必须信守诺言。

    清楚明确的表达你的问题以及需求

    漫无边际的提问是近乎无休无止的时间黑洞。最有可能给你有用答案的人通常也正是最忙的人(他们忙是因为要亲自完成大部分工作)。这样的人对无节制的时间黑洞相当厌恶,所以他们也倾向于厌恶那些漫无边际的提问。

    如果你明确表述需要回答者做什么(如提供指点、发送一段代码、检查你的补丁、或是其他等等),就最有可能得到有用的答案。因为这会定出一个时间和精力的上限,便于回答者能集中精力来帮你。这么做很棒。

    要理解专家们所处的世界,请把专业技能想像为充裕的资源,而回复的时间则是稀缺的资源。你要求他们奉献的时间越少,你越有可能从真正专业而且很忙的专家那里得到解答。

    所以,界定一下你的问题,使专家花在辨识你的问题和回答所需要付出的时间减到最少,这技巧对你有用答案相当有帮助 —— 但这技巧通常和简化问题有所区别。因此,问我想更好的理解 X,可否指点一下哪有好一点说明?通常比问你能解释一下 X 吗?更好。如果你的代码不能运作,通常请别人看看哪里有问题,比要求别人替你改正要明智得多。

    询问有关代码的问题时

    别要求他人帮你调试有问题的代码,不提示一下应该从何入手。张贴几百行的代码,然后说一声:它不能工作会让你完全被忽略。只贴几十行代码,然后说一句:在第七行以后,我期待它显示,但实际出现的是比较有可能让你得到回应。

    最有效描述程序问题的方法是提供最精简的 Bug 展示测试用例(bug-demonstrating test case)。什么是最精简的测试用例?那是问题的缩影;一小个程序片段能刚好展示出程序的异常行为,而不包含其他令人分散注意力的内容。怎么制作最精简的测试用例?如果你知道哪一行或哪一段代码会造成异常的行为,复制下来并加入足够重现这个状况的代码(例如,足以让这段代码能被编译/直译/被应用程序处理)。如果你无法将问题缩减到一个特定区块,就复制一份代码并移除不影响产生问题行为的部分。总之,测试用例越小越好(查看话不在多而在精一节)。

    一般而言,要得到一段相当精简的测试用例并不太容易,但永远先尝试这样做的是种好习惯。这种方式可以帮助你了解如何自行解决这个问题 —— 而且即使你的尝试不成功,黑客们也会看到你在尝试取得答案的过程中付出了努力,这可以让他们更愿意与你合作。

    如果你只是想让别人帮忙审查(Review)一下代码,在信的开头就要说出来,并且一定要提到你认为哪一部分特别需要关注以及为什么。

    别把自己家庭作业的问题贴上来

    黑客们很擅长分辨哪些问题是家庭作业式的问题;因为我们中的大多数都曾自己解决这类问题。同样,这些问题得由你来搞定,你会从中学到东西。你可以要求给点提示,但别要求得到完整的解决方案。

    如果你怀疑自己碰到了一个家庭作业式的问题,但仍然无法解决,试试在使用者群组,论坛或(最后一招)在项目的使用者邮件列表或论坛中提问。尽管黑客们会看出来,但一些有经验的使用者也许仍会给你一些提示。

    去掉无意义的提问句

    避免用无意义的话结束提问,例如有人能帮我吗?或者这有答案吗?。

    首先:如果你对问题的描述不是很好,这样问更是画蛇添足。

    其次:由于这样问是画蛇添足,黑客们会很厌烦你 —— 而且通常会用逻辑上正确,但毫无意义的回答来表示他们的蔑视, 例如:没错,有人能帮你或者不,没答案。

    一般来说,避免用 是或否、对或错、有或没有类型的问句,除非你想得到是或否类型的回答。

    即使你很急也不要在标题写紧急

    这是你的问题,不是我们的。宣称紧急极有可能事与愿违:大多数黑客会直接删除无礼和自私地企图即时引起关注的问题。更严重的是,紧急这个字(或是其他企图引起关注的标题)通常会被垃圾信过滤器过滤掉 —— 你希望能看到你问题的人可能永远也看不到。

    有半个例外的情况是,如果你是在一些很高调,会使黑客们兴奋的地方,也许值得这样去做。在这种情况下,如果你有时间压力,也很有礼貌地提到这点,人们也许会有兴趣回答快一点。

    当然,这风险很大,因为黑客们兴奋的点多半与你的不同。譬如从 NASA 国际空间站(International Space Station)发这样的标题没有问题,但用自我感觉良好的慈善行为或政治原因发肯定不行。事实上,张贴诸如紧急:帮我救救这个毛绒绒的小海豹!肯定让你被黑客忽略或惹恼他们,即使他们认为毛绒绒的小海豹很重要。

    如果你觉得这点很不可思议,最好再把这份指南剩下的内容多读几遍,直到你弄懂了再发文。

    礼多人不怪,而且有时还很有帮助

    彬彬有礼,多用请和谢谢您的关注,或谢谢你的关照。让大家都知道你对他们花时间免费提供帮助心存感激。

    坦白说,这一点并没有比清晰、正确、精准并合法语法和避免使用专用格式重要(也不能取而代之)。黑客们一般宁可读有点唐突但技术上鲜明的 Bug 报告,而不是那种有礼但含糊的报告。(如果这点让你不解,记住我们是按问题能教给我们什么来评价问题的价值的)

    然而,如果你有一串的问题待解决,客气一点肯定会增加你得到有用回应的机会。

    (我们注意到,自从本指南发布后,从资深黑客那里得到的唯一严重缺陷反馈,就是对预先道谢这一条。一些黑客觉得先谢了意味着事后就不用再感谢任何人的暗示。我们的建议是要么先说先谢了,然后事后再对回复者表示感谢,或者换种方式表达感激,譬如用谢谢你的关注或谢谢你的关照。)

    问题解决后,加个简短的补充说明

    问题解决后,向所有帮助过你的人发个说明,让他们知道问题是怎样解决的,并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注,应该在那里贴一个说明比较恰当。

    最理想的方式是向最初提问的话题回复此消息,并在标题中包含已修正,已解决或其它同等含义的明显标记。在人来人往的邮件列表里,一个看见讨论串问题 X 和问题 X - 已解决的潜在回复者就明白不用再浪费时间了(除非他个人觉得问题 X 的有趣),因此可以利用此时间去解决其它问题。

    补充说明不必很长或是很深入;简单的一句你好,原来是网线出了问题!谢谢大家 – Bill 比什么也不说要来的好。事实上,除非结论真的很有技术含量,否则简短可爱的小结比长篇大论更好。说明问题是怎样解决的,但大可不必将解决问题的过程复述一遍。

    对于有深度的问题,张贴调试记录的摘要是有帮助的。描述问题的最终状态,说明是什么解决了问题,在此之后才指明可以避免的盲点。避免盲点的部分应放在正确的解决方案和其它总结材料之后,而不要将此信息搞成侦探推理小说。列出那些帮助过你的名字,会让你交到更多朋友。

    除了有礼貌和有内涵以外,这种类型的补充也有助于他人在邮件列表/新闻群组/论坛中搜索到真正解决你问题的方案,让他们也从中受益。

    至少,这种补充有助于让每位参与协助的人因问题的解决而从中得到满足感。如果你自己不是技术专家或者黑客,那就相信我们,这种感觉对于那些你向他们求助的大师或者专家而言,是非常重要的。问题悬而未决会让人灰心;黑客们渴望看到问题被解决。好人有好报,满足他们的渴望,你会在下次提问时尝到甜头。

    思考一下怎样才能避免他人将来也遇到类似的问题,自问写一份文件或加个常见问题(FAQ)会不会有帮助。如果是的话就将它们发给维护者。

    在黑客中,这种良好的后继行动实际上比传统的礼节更为重要,也是你如何透过善待他人而赢得声誉的方式,这是非常有价值的资产。

    如何解读答案

    RTFM 和 STFW:如何知道你已完全搞砸了

    有一个古老而神圣的传统:如果你收到 RTFM (Read The Fucking Manual)的回应,回答者认为你应该去读他妈的手册。当然,基本上他是对的,你应该去读一读。

    RTFM 有一个年轻的亲戚。如果你收到 STFW(Search The Fucking Web)的回应,回答者认为你应该到他妈的网上搜索。那人多半也是对的,去搜索一下吧。(更温和一点的说法是 Google 是你的朋友!)

    在论坛,你也可能被要求去爬爬论坛的旧文。事实上,有人甚至可能热心地为你提供以前解决此问题的讨论串。但不要依赖这种关照,提问前应该先搜索一下旧文。

    通常,用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址,而且他们打这些字的时候也正在读着。这些答复意味着回答者认为

    • 你需要的信息非常容易获得
    • 你自己去搜索这些信息比灌给你,能让你学到更多

    你不应该因此不爽;依照黑客的标准,他已经表示了对你一定程度的关注,而没有对你的要求视而不见。你应该对他祖母般的慈祥表示感谢。

    如果还是搞不懂

    如果你看不懂回应,别立刻要求对方解释。像你以前试着自己解决问题时那样(利用手册,FAQ,网络,身边的高手),先试着去搞懂他的回应。如果你真的需要对方解释,记得表现出你已经从中学到了点什么。

    比方说,如果我回答你:看来似乎是 zentry 卡住了;你应该先清除它。,然后,这是一个很糟的后续问题回应:zentry 是什么? 好的问法应该是这样:哦~~~我看过说明了但是只有 -z 和 -p 两个参数中提到了 zentries,而且还都没有清楚的解释如何清除它。你是指这两个中的哪一个吗?还是我看漏了什么?

    处理无礼的回应

    很多黑客圈子中看似无礼的行为并不是存心冒犯。相反,它是直接了当,一针见血式的交流风格,这种风格更注重解决问题,而不是使人感觉舒服而却模模糊糊。

    如果你觉得被冒犯了,试着平静地反应。如果有人真的做了出格的事,邮件列表、新闻群组或论坛中的前辈多半会招呼他。如果这没有发生而你却发火了,那么你发火对象的言语可能在黑客社区中看起来是正常的,而你将被视为有错的一方,这将伤害到你获取信息或帮助的机会。

    另一方面,你偶尔真的会碰到无礼和无聊的言行。与上述相反,对真正的冒犯者狠狠地打击,用犀利的语言将其驳得体无完肤都是可以接受的。然而,在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔,黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外人,避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光,这时最好不要把手放在键盘上以免冒险。

    (有些人断言很多黑客都有轻度的自闭症或亚斯伯格综合症,缺少用于润滑人类社会正常交往所需的神经。这既可能是真也可能是假的。如果你自己不是黑客,兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了,我们不在乎。我们喜欢我们现在这个样子,并且通常对病患标记都有站得住脚的怀疑)。

    Jeff Bigler 的观察总结和这个相关也值得一读 (tact filters)。

    在下一节,我们会谈到另一个问题,当你行为不当时所会受到的冒犯。

    如何避免扮演失败者

    在黑客社区的论坛中有那么几次你可能会搞砸 —— 以本指南所描述到的或类似的方式。而你会在公开场合中被告知你是如何搞砸的,也许攻击的言语中还会带点夹七夹八的颜色。

    这种事发生以后,你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被口头攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、忘了关马桶盖等等。相反地,你该这么做:

    熬过去,这很正常。事实上,它是有益健康且合理的。

    社区的标准不会自行维持,它们是通过参与者积极而公开地执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送,它不是这样运作的。当有人评论你的一个说法有误或者提出不同看法时,坚持声称受到个人攻击也毫无益处,这些都是失败者的态度。

    也有其它的黑客论坛,受过高礼节要求的误导,禁止参与者张贴任何对别人帖子挑毛病的消息,并声称如果你不想帮助用户就闭嘴。 结果造成有想法的参与者纷纷离开,这么做只会使它们沦为毫无意义的唠叨与无用的技术论坛。

    夸张的讲法是:你要的是“友善”(以上述方式)还是有用?两个里面挑一个。

    记着:当黑客说你搞砸了,并且(无论多么刺耳)告诉你别再这样做时,他正在为关心你和他的社区而行动。对他而言,不理你并将你从他的生活中滤掉更简单。如果你无法做到感谢,至少要表现得有点尊严,别大声哀嚎,也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者,就指望别人像对待脆弱的洋娃娃那样对你。

    有时候,即使你没有搞砸(或者只是在他的想像中你搞砸了),有些人也会无缘无故地攻击你本人。在这种情况下,抱怨倒是真的会把问题搞砸。

    这些来找麻烦的人要么是毫无办法但自以为是专家的不中用家伙,要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬,要么用自己的方式对付他们。这些来找麻烦的人在给他们自己找麻烦,这点你不用操心。

    也别让自己卷入口水战,最好不要理睬大多数的口水战 —— 当然,这是在你检验它们只是口水战,并且未指出你有搞砸的地方,同时也没有巧妙地将问题真正的答案藏于其后(这也是有可能的)。

    不该问的问题

    以下是几个经典蠢问题,以及黑客没回答时心中所想的:

    问题:我能在哪找到 X 程序或 X 资源?

    问题:我怎样用 X 做 Y?

    问题:如何设定我的 shell 提示?

    问题:我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 档案转换为 TeX 格式吗?

    问题:我的程序/设定/SQL 语句没有用

    问题:我的 Windows 电脑有问题,你能帮我吗?

    问题:我的程序不会动了,我认为系统工具 X 有问题

    问题:我在安装 Linux(或者 X )时有问题,你能帮我吗?

    问题:我怎么才能 PJ root 帐号/窃取 OP 特权/读别人的邮件呢?


    问题:我能在哪找到 X 程序或 X 资源?

    回答:就在我找到它的地方啊,白痴 —— 搜索引擎的那一头。天哪!难道还有人不会用 Google 吗?

    问题:我怎样用 X 做 Y?

    回答:如果你想解决的是 Y ,提问时别给出可能并不恰当的方法。这种问题说明提问者不但对 X 完全无知,也对 Y 要解决的问题糊涂,还被特定形势禁锢了思维。最好忽略这种人,等他们把问题搞清楚了再说。

    问题:如何设定我的 shell 提示??

    回答:如果你有足够的智慧提这个问题,你也该有足够的智慧去 RTFM,然后自己去找出来。

    问题:我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 档案转换为 TeX 格式吗?

    回答:试试看就知道了。如果你试过,你既知道了答案,就不用浪费我的时间了。

    问题:我的{程序/设定/SQL 语句}不工作

    回答:这不算是问题吧,我对要我问你二十个问题才找得出你真正问题的问题没兴趣 —— 我有更有意思的事要做呢。在看到这类问题的时候,我的反应通常不外如下三种

    • 你还有什么要补充的吗?
    • 真糟糕,希望你能搞定。
    • 这关我屁事?

    问题:我的 Windows 电脑有问题,你能帮我吗?

    回答:能啊,扔掉微软的垃圾,换个像 Linux 或 BSD 的开源操作系统吧。

    注意:如果程序有官方版 Windows 或者与 Windows 有互动(如 Samba),你可以问与 Windows 相关的问题, 只是别对问题是由 Windows 操作系统而不是程序本身造成的回复感到惊讶, 因为 Windows 一般来说实在太烂,这种说法通常都是对的。

    问题:我的程序不会动了,我认为系统工具 X 有问题

    回答:你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与函数库档案有明显缺陷的人,更有可能的是你完全没有根据。不同凡响的说法需要不同凡响的证据,当你这样声称时,你必须有清楚而详尽的缺陷说明文件作后盾。

    问题:我在安装 Linux(或者 X )时有问题,你能帮我吗?

    回答:不能,我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的 Linux 使用群组者寻求实际的指导吧(你能在这儿找到使用者群组的清单)。

    注意:如果安装问题与某 Linux 的发行版有关,在它的邮件列表、论坛或本地使用者群组中提问也许是恰当的。此时,应描述问题的准确细节。在此之前,先用 Linux 和所有被怀疑的硬件作关键词仔细搜索。

    问题:我怎么才能 PJ root 帐号/窃取 OP 特权/读别人的邮件呢?

    回答:想要这样做,说明了你是个卑鄙小人;想找个黑客帮你,说明你是个白痴!

    好问题与蠢问题

    最后,我将透过举一些例子,来说明怎样聪明的提问;同一个问题的两种问法被放在一起,一种是愚蠢的,另一种才是明智的。

    蠢问题:

    我可以在哪儿找到关于 Foonly Flurbamatic 的资料?

    这种问法无非想得到 STFW 这样的回答。

    聪明问题:

    我用 Google 搜索过 “Foonly Flurbamatic 2600”,但是没找到有用的结果。谁知道上哪儿去找对这种设备编程的资料?

    这个问题已经 STFW 过了,看起来他真的遇到了麻烦。

    蠢问题:

    我从 foo 项目找来的源码没法编译。它怎么这么烂?

    他觉得都是别人的错,这个傲慢自大的提问者。

    聪明问题:

    foo 项目代码在 Nulix 6.2 版下无法编译通过。我读过了 FAQ,但里面没有提到跟 Nulix 有关的问题。这是我编译过程的记录,我有什么做的不对的地方吗?

    提问者已经指明了环境,也读过了 FAQ,还列出了错误,并且他没有把问题的责任推到别人头上,他的问题值得被关注。

    蠢问题:

    我的主机板有问题了,谁来帮我?

    某黑客对这类问题的回答通常是:好的,还要帮你拍拍背和换尿布吗?,然后按下删除键。

    聪明问题:

    我在 S2464 主机板上试过了 X 、 Y 和 Z ,但没什么作用,我又试了 A 、 B 和 C 。请注意当我尝试 C 时的奇怪现象。显然 florbish 正在 grommicking,但结果出人意料。通常在 Athlon MP 主机板上引起 grommicking 的原因是什么?有谁知道接下来我该做些什么测试才能找出问题?

    这个家伙,从另一个角度来看,值得去回答他。他表现出了解决问题的能力,而不是坐等天上掉答案。

    在最后一个问题中,注意告诉我答案和给我启示,指出我还应该做什么诊断工作之间微妙而又重要的区别。

    事实上,后一个问题源自于 2001 年 8 月在 Linux 内核邮件列表(lkml)上的一个真实的提问。我(Eric)就是那个提出问题的人。我在 Tyan S2464 主板上观察到了这种无法解释的锁定现象,列表成员们提供了解决这一问题的重要信息。

    通过我的提问方法,我给了别人可以咀嚼玩味的东西;我设法让人们很容易参与并且被吸引进来。我显示了自己具备和他们同等的能力,并邀请他们与我共同探讨。通过告诉他们我所走过的弯路,以避免他们再浪费时间,我也表明了对他们宝贵时间的尊重。

    事后,当我向每个人表示感谢,并且赞赏这次良好的讨论经历的时候, 一个 Linux 内核邮件列表的成员表示,他觉得我的问题得到解决并非由于我是这个列表中的名人,而是因为我用了正确的方式来提问。

    黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙;我相信他是对的,如果我像个乞讨者那样提问,不论我是谁,一定会惹恼某些人或者被他们忽视。他建议我记下这件事,这直接导致了本指南的出现。

    如果得不到回答

    如果仍得不到回答,请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。没有回应不代表你被忽视,虽然不可否认这种差别很难区分。

    总的来说,简单的重复张贴问题是个很糟的点子。这将被视为无意义的喧闹。有点耐心,知道你问题答案的人可能生活在不同的时区,可能正在睡觉,也有可能你的问题一开始就没有组织好。

    你可以通过其他渠道获得帮助,这些渠道通常更适合初学者的需要。

    有许多网上的以及本地的使用者群组,由热情的软件爱好者(即使他们可能从没亲自写过任何软件)组成。通常人们组建这样的团体来互相帮助并帮助新手。

    另外,你可以向很多商业公司寻求帮助,不论公司大还是小。别为要付费才能获得帮助而感到沮丧!毕竟,假使你的汽车发动机汽缸密封圈爆掉了 —— 完全可能如此 —— 你还得把它送到修车铺,并且为维修付费。就算软件没花费你一分钱,你也不能强求技术支持总是免费的。

    对像是 Linux 这种大众化的软件,每个开发者至少会对应到上万名使用者。根本不可能由一个人来处理来自上万名使用者的求助电话。要知道,即使你要为这些协助付费,和你所购买的同类软件相比,你所付出的也是微不足道的(通常封闭源代码软件的技术支持费用比开源软件的要高得多,且内容也没那么丰富)。

    如何更好地回答问题

    态度和善一点。问题带来的压力常使人显得无礼或愚蠢,其实并不是这样。

    对初犯者私下回复。对那些坦诚犯错之人没有必要当众羞辱,一个真正的新手也许连怎么搜索或在哪找常见问题都不知道。

    如果你不确定,一定要说出来!一个听起来权威的错误回复比没有还要糟,别因为听起来像个专家很好玩,就给别人乱指路。要谦虚和诚实,给提问者与同行都树个好榜样。

    如果帮不了忙,也别妨碍他。不要在实际步骤上开玩笑,那样也许会毁了使用者的设置 —— 有些可怜的呆瓜会把它当成真的指令。

    试探性的反问以引出更多的细节。如果你做得好,提问者可以学到点东西 —— 你也可以。试试将蠢问题转变成好问题,别忘了我们都曾是新手。

    尽管对那些懒虫抱怨一声 RTFM 是正当的,能指出文件的位置(即使只是建议个 Google 搜索关键词)会更好。

    如果你决定回答,就请给出好的答案。当别人正在用错误的工具或方法时别建议笨拙的权宜之计(workaround),应推荐更好的工具,重新界定问题。

    正面的回答问题!如果这个提问者已经很深入的研究而且也表明已经试过 X 、 Y 、 Z 、 A 、 B 、 C 但没得到结果,回答 试试看 A 或是 B 或者 试试 X 、 Y 、 Z 、 A 、 B 、 C 并附上一个链接一点用都没有。

    帮助你的社区从问题中学习。当回复一个好问题时,问问自己如何修改相关文件或常见问题文件以免再次解答同样的问题?,接着再向文件维护者发一份补丁。

    如果你是在研究一番后才做出的回答,展现你的技巧而不是直接端出结果。毕竟授人以鱼不如授人以渔。

    相关资源

    如果你需要个人电脑、Unix 系统和网络如何运作的基础知识,参阅 Unix 系统和网络基本原理。

    当你发布软件或补丁时,试着按软件发布实践操作。

    鸣谢

    Evelyn Mitchel 贡献了一些愚蠢问题例子并启发了编写如何更好地回答问题这一节, Mikhail Ramendik 贡献了一些特别有价值的建议和改进。

    文章作者: Eric Steven Raymond, Rick Moen
    文章链接: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way
    版权声明: Copyleft 2001 by D.H.Grand(nOBODY/Ginux), 2010 by Gasolin, 2015 by Ryan Wu,本中文指南是基于原文 3.10 版以及 2010 年由 Gasolin 所翻译版本的最新翻译
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/how-to-enjoy-joox-music-service-in-mainland-china/index.html b/posts/how-to-enjoy-joox-music-service-in-mainland-china/index.html new file mode 100644 index 000000000..12f565aad --- /dev/null +++ b/posts/how-to-enjoy-joox-music-service-in-mainland-china/index.html @@ -0,0 +1,19 @@ +如何在中国大陆享受 JOOX 音乐服务 | CC的部落格

    如何在中国大陆享受 JOOX 音乐服务

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    如何在中国大陆享受 JOOX 音乐服务 本篇教程不需要特殊上网工具,但会提及

    在开始之前你可能需要知道JOOX什么,看了标题你知道它能提供流媒体音乐服务,但你需要了解一下它的身世

    JOOX 是一个起源于香港的正版音乐流媒体服务,提供包括三大唱片公司在内,超过 200 万首高品质歌曲的收听与下载。该服务发布于 2014 年 12 月,支持 Android 和 iOS 平台,在香港等地区运营。但现在它已在七个国家或地区运营,并支持了 web 和 win, mac 客户端可上官网查看,但你显然能发现页脚写着Tencent,啊没错就是你想的腾讯,其实你可以理解为海外版 QQ 音乐,但腾讯音乐娱乐的投资还不止这些,但这不是本文重点,前面提到,由于版权原因,只在特定地区运营,也就是限制了 IP,而要享受 JOOX 提供的服务,就得让你的 IP 被识别为它支持的地区 IP,大家通常都是使用特殊上网工具,来访问,但我发现它对 IP 限制并没有那么严格,那么是否可以伪造 IP 呢

    火狐浏览器

    打开浏览器,插件商店搜索X-Forwarded-For Header

    安装后打开你的搜索引擎,搜索你想使用地区 IP,比如香港或者泰国,马来西亚等,填入 IP 即可,就像图中所示

    然后打开JOOX 官网,就会根据你的 IP 自动识别区域,不同地区曲库不同所以根据个人需要来哦,接下来注册账号,不过如果是不使用中文的地区,可以在侧栏点击lang切换语言为英语哦(不过网页翻译也行),以下以泰国作为示例

    点击右上角 Sign Up 注册账号,根据相应要求填写信息,注册即可

    你可以使用邮箱注册,手机号绑定绑定大陆手机号也是可以的,当然作为腾讯家的东西,你可以绑定微信,是不是很方便呢,这些你以后可以在 APP 中操作,这里不再赘述,登陆后你就可以尽情享受 JOOX 提供的音乐服务了,并且如果你以后使用JOOX APP是可以全球不受限制听歌哦,下载了虽然会提示网络问题,但只要你登陆后就可以尽情享受音乐服务啦,但你第一次注册了就会锁定你的区域啦,因此你要使用其他地区曲库只能另外注册帐号了

    题外话:有很多软件或者项目支持下载 JOOX 音乐,不过说实话泰国搜索做的太差了,接口的话也不是那么可靠,好在没有服务端没有加密,所以抓包还是很好解决的,但还是提倡大家尊重版权和音乐创作者的辛苦,在线听吧,而且 JOOX 免费任务得到的 VIP 够你一直是 VIP 了,所以还是推荐大家使用官方正版渠道听歌的

    至于怎么下载 JOOX APP,安卓用户如果使用华为手机在应用市场切换区域为服务区域,搜索 JOOX 即可下载,或者在对于服务区 Google Play(IP)搜索下载即可(搜索不到说明不支持当前区域),当然直接下载安装包也是可以的,第三方市场比如 APKpure 还是值得信赖的;IOS 用户只能靠服务区域 ID 进去苹果商店下载了

    Chrome 浏览器,QQ 浏览器之类的呢

    打开浏览器,插件商店搜索Header-Editor,至于怎么访问谷歌应用商店,不用我多说了吧

    安装后按照下图所示填入即可,和火狐差不多

    但记得做好分类,以便于切换,即Description,要切换时记得Active选中即可,不使用时记得关闭插件或取消勾选以免影响国内一些网站的访问

    总结

    X-Forwarded-For 是一个 HTTP 扩展头部,主要是为了让 Web 服务器获取访问用户的真实 IP 地址(其实这个真实未必是真实的,后面会说到)。那为什么 Web 服务器只有通过 X-Forwarded-For 头才能获取真实的 IP?这里用 PHP 语言来说明,不明白原理的开发者为了获取客户 IP,会使用 $_SERVER[‘REMOTE_ADDR’] 变量,这个服务器变量表示和 Web 服务器握手的 IP 是什么(这个不能伪造)。但是很多用户都通过代理来访问服务器的,那么假如使用该全局变量,PHP 获取到的 IP 就是代理服务器的 IP(不是用户的)。可能很多人看的晕乎乎的,那么看看一个请求可能经过的路径:客户端=>(正向代理=>透明代理=>服务器反向代理=>)Web 服务器。其中正向代理、透明代理、服务器反向代理这三个环节并不一定存在。

    什么是正向代理呢,很多企业会在自己的出口网关上设置代理(主要是为了加速和节省流量)。透明代理可能是用户自己设置的代理(比如为了 FQ,这样也绕开了公司的正向代理)。服务器反向代理是部署在 Web 服务器前面的,主要原因是为了负载均衡和安全考虑。

    现在假设几种情况:假如客户端直接连接 Web 服务器(假设 Web 服务器有公网地址),则 $_SERVER[‘REMOTE_ADDR’] 获取到的是客户端的真实 IP 。假设 Web 服务器前部署了反向代理(比如 Nginx),则 $_SERVER[‘REMOTE_ADDR’] 获取到的是反向代理设备的 IP(Nginx)。假设客户端通过正向代理直接连接 Web 服务器(假设 Web 服务器有公网地址),则 $_SERVER[‘REMOTE_ADDR’] 获取到的正向代理设备的 IP 。其实这里的知识点很多,记住一点就行了,$_SERVER[‘REMOTE_ADDR’] 获取到的 IP 是 Web 服务器 TCP 连接的 IP(这个不能伪造,一般 Web 服务器也不会修改这个头)。

    这个方法也能用于一些国外其他网站,但对于要求比较严格的,大家只能老老实实使用代理咯,好了,今天就讲到这里,我们下篇文章见!

    补充更新

    这个来自 Github 上的一个项目可以用来下载 JOOX 歌曲,不过曲库是印尼,所以不是很推荐

    此外,由于网页版采用了 PWA 技术,所以如果你使用chrome之类的浏览器,地址栏会弹出一个加号对话框,是否安装应用到本地,这样以后直接在应用或者桌面双击即可(由于缓存,你以后是不需要再用到插件的,直接登录即可)

    但是这些都准备好了,不免有时候过于麻烦,官方提供的网页套壳客户端并不是很推荐(需要对应地区代理),我们可以使用第三方(来自 github)前往下载界面下载对应的安装包即可使用,帮我们跳过了地区限制,直接登录即可。默认用打开的话,还是会显示国际版 intl,地区版权限制之类的,而且官方很久不更新了,推荐这个(泰国人做的)

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/how-to-enjoy-joox-music-service-in-mainland-china/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/how-to-hide-hexo-articles-gracefully/index.html b/posts/how-to-hide-hexo-articles-gracefully/index.html new file mode 100644 index 000000000..9e203dcdb --- /dev/null +++ b/posts/how-to-hide-hexo-articles-gracefully/index.html @@ -0,0 +1,20 @@ +如何优雅隐藏 Hexo 文章 | CC的部落格

    如何优雅隐藏 Hexo 文章

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀,自动同步更新至CC 的部落格

    延迟发布

    • _config.yml( Hexo 配置文件)关闭显示未来文章(即将future配置为 false ,这样如果你手动指定日期晚于当前时间,就不会生成,当你想要发布文章时修改一下发布时间,或者到了预定发布的时间时重新部署一次即可展示文章
    # Writing
    new_post_name: :title.md
    default_layout: post
    auto_spacing: true
    titlecase: false
    external_link:
    enable: true
    field: site
    exclude: ""
    filename_case: 0
    render_drafts: false
    post_asset_folder: false
    relative_link: false
    future: true

    发布状态

    • 在文章 Markdown 文件Front-Matter部分配置published参数
    ---
    published: false
    ---

    即可达到与上面一样的效果,这样当我们认为文章可以公开时,再设为true或者删掉这个配置即可,同样由于是静态博客,仍需要重新部署一次才会显示

    首页隐藏

    • 前两种方式如果你的源码仓库闭源的话,是完全隐藏的,只有你知道,但是有时候我们只想在首页隐藏部分文章,而不是不公开文章,我们需要更换首页生成插件,执行以下命令
    $ npm uninstall hexo-generator-index
    $ npm install hexo-generator-indexed

    隐藏文章 ,在文章的 Front-matter 中增加一个 hide 参数用来隐藏

    ---
    title: example
    hide: true
    ---
    隐藏特定分类中的文章,在 Hexo 的 `_config.yml` 中可以通过 `hide_categories` 选项设置隐藏某个分类下的文章,例如:
    +
    hide_categories:
    - categorie1
    - categorie2

    存为草稿

    对于我来说,由于我使用的是语雀,在未发布前,都储存在草稿箱所以不会有这个问题,而我发布后文章会同步到源代码仓库posts分支;但总有小伙伴那么几篇文章不想让别人看到,所以水了这篇文章;并且生成后的代码仓库大多数情况下是公开的,所以还是推荐没写完就不要发布了,留在草稿箱,即使你指定一个只有你自己知道的路径,虽然一般人不会闲得慌去看你仓库,但并没有达到不想公开的效果,因此可以在博客目录.gitignore文件添加忽略草稿目录

    .DS_Store
    Thumbs.db
    db.json
    hexo.bat
    yuque.json
    *.log
    public
    node_modules
    .deploy*
    .nojekyll
    source/_posts/语雀
    themes/butterfly/.git
    source/_drafts

    当然在使用草稿功能前,注意检查_config.ymlHexo 配置文件是否关闭显示(渲染)草稿

    render_drafts: false

    此外,在最开始的HexoWriting 部分配置项中我们知道default_layout: post,即默认布局为post文章类别,又因为new可以简写为n,因此默认情况下以下 3 条新建文章命令等效

    $ hexo new post <title>

    $ hexo new <title>

    $ hexo n <title>

    同理,在 Hexo 官方文档中也有提到,如果要新建草稿,可使用如下命令

    $ hexo new draft <title>

    $ hexo n draft <title>

    当然我们还要知道默认的 layout 模板文件存在根目录/scaffolds下(我们可以自行新建或修改模板,这里不做展开),草稿存在根目录/source/_drafts下,文章存在根目录/source/_posts 刚刚提到了 Hexo 的一种特殊布局:draft,这种布局在建立时会被保存到 source/_drafts文件夹,您可通过publish 命令将草稿移动到 source/_posts 文件夹,该命令的使用方式与 new 十分类似,您也可在命令中指定 layout 来指定布局。

    $ hexo publish [layout] <title>

    那么如果我们要发布草稿即可使用如下命令

    $ hexo publish <title>

    $ hexo p <title>

    草稿默认不会显示在页面中,您可在执行时加上 --draft参数,或是把 render_drafts 参数设为 true 来预览草稿。

    $ hexo s --draft
    $ hexo g --draft

    若日后想将正式文章转为为草稿,只需手动将文章从source/_posts目录移动到source/_drafts目录即可。

    source

    资源文件夹,除了模板以外的 Asset,例如 CSS、JavaScript 文件等,都应该放在这个文件夹中。文件或文件夹开头名称为 _(下划线线)或隐藏的文件会被忽略。如果文件可以被渲染的话,会经过解析然后储存到 public 文件夹,否则会直接拷贝到 public 文件夹。

    资源文件夹是存放用户资源的地方。除 _posts 文件夹之外,开头命名为 _ (下划线)的文件 / 文件夹和隐藏的文件将会被忽略。Markdown 和 HTML 文件会被解析并放到 public 文件夹,而其他文件会被拷贝过去。

    官方其实考虑到这个问题,事实上我们在_post(文章)文件夹内可以按照类别来存放文章,这样做既方便我们查找,也能形成系统性文档,所以可以建立不同的子文件夹存放不同类别的文章,说到这可能你想到了,如果我建立一个文件夹_还未准备好发布的文章,或者把文件夹设置为隐藏,那这样也能跳过渲染实现和草稿一样的效果。

    题外话

    而对于加密这个操作,我觉得是没有必要了,但也有对应的使用场景,各取所需吧。

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/how-to-hide-hexo-articles-gracefully/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/i-dont-really-want-html/index.html b/posts/i-dont-really-want-html/index.html new file mode 100644 index 000000000..abe7b9cd2 --- /dev/null +++ b/posts/i-dont-really-want-html/index.html @@ -0,0 +1,19 @@ +我真的不想要 .html | CC的部落格

    我真的不想要 .html

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    我真的不想要.html

    起因

    Coding  的旧版网站列表突然消失,以为要强制迁移新版

    于是临时解析到了 Vercel,但是晚上它又好了

    发现问题

    但部署刷新几遍发现没有变化,当时德目录结构没有 live 文件夹里面放 index.html,会想到主页的.html后缀问题,我去前往主页分页查看,果然不加.html直接公益 404,那么就得为两种解析方式都准备好源文件

    解决问题

    主页怎么办

    这是废话

    const gulp = require("gulp");
    const minifycss = require("gulp-clean-css");
    const uglify = require("gulp-uglify");
    const htmlmin = require("gulp-htmlmin");
    const cssnano = require("gulp-cssnano");
    const htmlclean = require("gulp-htmlclean");
    const del = require("del");
    const babel = require("gulp-babel");
    const autoprefixer = require("gulp-autoprefixer");
    const connect = require("gulp-connect");
    const pug = require("gulp-pug");
    const sass = require("gulp-sass");
    const rename = require("gulp-rename");
    sass.compiler = require("node-sass");

    const config = require("./config.json");

    gulp.task("clean", function () {
    return del(["./dist/css/", "./dist/js/"]);
    });

    gulp.task("css", function () {
    return gulp
    .src("./src/css/*.scss")
    .pipe(sass().on("error", sass.logError))
    .pipe(minifycss({ compatibility: "ie8" }))
    .pipe(autoprefixer({ overrideBrowserslist: ["last 2 version"] }))
    .pipe(cssnano({ reduceIdents: false }))
    .pipe(gulp.dest("./dist/css"));
    });

    gulp.task("html", function () {
    return gulp
    .src("./dist/*.html")
    .pipe(htmlclean())
    .pipe(htmlmin())
    .pipe(gulp.dest("./dist"));
    });

    gulp.task("js", function () {
    return gulp
    .src("./src/js/*.js")
    .pipe(babel({ presets: ["@babel/preset-env"] }))
    .pipe(uglify())
    .pipe(gulp.dest("./dist/js"));
    });

    gulp.task("pug", function () {
    return gulp
    .src("./src/*.pug")
    .pipe(pug({ data: config }))
    .pipe(gulp.dest("./dist"));
    });
    gulp.task("redirect", function (done) {
    config.redirect.forEach((item) => {
    // item 为redirect的列表
    let data = {
    redirect: item,
    count: config.count,
    template: item.template || "redirect",
    };
    gulp
    .src(`./src/redirect/${data.template}.pug`)
    .pipe(pug({ data: data }))
    .pipe(rename("index.html"))
    .pipe(gulp.dest(`./dist/${item.path}`));
    });
    done();
    });
    gulp.task("assets", function () {
    return gulp.src(["./src/assets/**/*"]).pipe(gulp.dest("./dist/assets"));
    });
    gulp.task("staticHtml", function () {
    return gulp.src(["./src/*.html"]).pipe(gulp.dest("./dist"));
    });
    gulp.task("test", gulp.series("redirect"));
    gulp.task("LICENSE", function () {
    return gulp.src(["./src/LICENSE"]).pipe(gulp.dest("./dist"));
    });

    gulp.task("txt", function () {
    return gulp.src(["./src/*.txt"]).pipe(gulp.dest("./dist"));
    });

    gulp.task("md", function () {
    return gulp.src(["./src/*.md"]).pipe(gulp.dest("./dist"));
    });

    gulp.task("sw", function () {
    return gulp.src(["./src/*.js"]).pipe(gulp.dest("./dist"));
    });

    gulp.task(
    "build",
    gulp.series(
    "clean",
    "assets",
    "staticHtml",
    "pug",
    "redirect",
    "css",
    "js",
    "html",
    "LICENSE",
    "txt",
    "md",
    "sw"
    )
    );
    gulp.task("default", gulp.series("build"));

    gulp.task("watch", function () {
    gulp.watch("./src/components/*.pug", gulp.parallel("pug"));
    gulp.watch("./src/pages/*.pug", gulp.parallel("pug"));
    gulp.watch("./src/*.pug", gulp.parallel("pug"));
    gulp.watch("./src/css/**/*.scss", gulp.parallel(["css"]));
    gulp.watch("./src/js/*.js", gulp.parallel(["js"]));
    connect.server({
    root: "dist",
    livereload: true,
    port: 4000,
    });
    });

    以上仅作为存档备份,万一哪天改没了,不想去找历史记录

    最笨的方法解决

    为了保险起见,我还是要确保双目录,境内外都能正常跳转

    //在生成静态文件并且压缩完毕后,新建文件夹,复制过去重命名为index.html即可保证coding,vercel都能不使用.html访问了,index.html和404.html因为两边都能正常跳转,我也不会通配,所以老老实实一条一条写(乐特说只有废物看文档,我就是废物,我还不想看)
    gulp.task("about", function () {
    return gulp
    .src("./dist/about.html")
    .pipe(rename("index.html"))
    .pipe(gulp.dest("./dist/about"));
    });

    gulp.task("link", function () {
    return gulp
    .src("./dist/link.html")
    .pipe(rename("index.html"))
    .pipe(gulp.dest("./dist/link"));
    });

    gulp.task("speak", function () {
    return gulp
    .src("./dist/speak.html")
    .pipe(rename("index.html"))
    .pipe(gulp.dest("./dist/speak"));
    });

    gulp.task("timeline", function () {
    return gulp
    .src("./dist/timeline.html")
    .pipe(rename("index.html"))
    .pipe(gulp.dest("./dist/timeline"));
    });

    //同时按照顺序添加任务
    gulp.task("build", gulp.series("html", "about", "link", "speak", "timeline"));

    这样生成的文件目录和预期相同

    但其实没必要这样麻烦,费力不讨好,改一改 gulpfile.js 这个文件生成文件的目录结构即可,或者往下看

    结果

    现在主页不管是Vercel还是Coding都能正常跳转脱掉.html了,并且可实现境外境内分流,限制境外用户访问某些页面(伪操作

    比如现在访问主站点直播界面,若是境外用户会显示(Vercel)

    但境内用户则正常(Coding)

    分析

    在路由表默认逻辑上,Vervel,Gitlab,一致,Github,Gitee``Coding,Netlify一致,所以上面的说法是不严谨的,用户可以在链接后加上.html则可正常访问相应内容,但至少所有镜像站点都可以正常跳转了,然后配合 DNS 分流解析即可实现上面的效果

    简单方式

    查看 Vercel 官方文档 发现如下内容

    Vercel uses Routes to define the behavior of how a request is handled by the routing layer. For example, you might use a Route to proxy a URL to another, redirect a client, or apply a header with the response to a request.

    By default, routing is defined by the filesystem of your deployment. For example, if a user makes a request to /123.png, and your [vercel.json](https://vercel.com/docs/configuration#project/routes) file does not contain any routes with a valid src matching that path, it will fallback to the filesystem and serve /123.png if it exists.

    NOTE: For Serverless Function routes, you can configure an /api directory to provide filesystem routing and handle dynamic routing with path segments, without the need for configuration.

    A Route can be defined within a project’s [vercel.json](https://vercel.com/docs/configuration#project/routes) configuration file as an object within an array assigned to the routes property, like the following which creates a simple proxy from one path to another:

    {
    "routes": [{ "src": "/about", "dest": "/about.html" }]
    }

    An example vercel.json file with a routes property that proxies one path to another upon request.

    Vercel Routes have multiple properties for each route object that help define the behavior of a response to each request to a particular path.

    src

    Type: String supporting PCRE Regex and Route Parameters like /product/(?<id>[^/]+).

    For each route, src is required to set the path which the behavior will affect.

    The following example shows a vercel.json configuration that takes a src path and proxies it to a destination[dest](https://vercel.com/docs/configuration#dest)path.

    {
    "routes": [{ "src": "/about", "dest": "/about.html" }]
    }

    An example vercel.json file with a routes property that proxies one path to another upon request.

    dest

    Type: String

    dest is used to proxy the [src](https://vercel.com/docs/configuration#src) path to another path, such as another URL or Vercel hosted Serverless Function.

    The example for the[src](https://vercel.com/docs/configuration#src)property shows how both methods work together to create a proxy.

    {
    "routes": [
    { "src": "/about", "dest": "https://about.me" },
    { "src": "/action", "dest": "my-serverless-function-action/index" }
    ]
    }

    An example vercel.json file with routes properties that proxy paths to another upon request.

    NOTE: You can point the dest path to any URL, Vercel hosted Serverless Function, or even non Vercel hosted URLs as shown in the code above. If you don’t perform any proxying, you can safely remove dest.

    {
    "routes": [{ "src": "/about" }]
    }

    This will route to /about without proxying, but routes like this are usually redundant with handle filesystem.

    这代表着我们可以按照上面的方式自定义路由表:即在根目录创建vercel.json来完成自定义,并完美去掉.html,解决这个问题,并且个人也是推荐这种更为简单的方法;而查看文档,我才发现 Vercel 真的是一个强大的静态托管平台,笔芯!

    所以 Vercel 方面,以我主页为例,就可以通过以下代码来解决啦

    {
    "routes": [
    { "src": "/about", "dest": "/about.html" },
    { "src": "/link", "dest": "/link.html" },
    { "src": "/speak", "dest": "/speak.html" },
    { "src": "/timeline", "dest": "/timeline.html" }
    ]
    }
    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/i-dont-really-want-html/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/implementation-of-simple-browser-update-push/index.html b/posts/implementation-of-simple-browser-update-push/index.html new file mode 100644 index 000000000..f9601e45c --- /dev/null +++ b/posts/implementation-of-simple-browser-update-push/index.html @@ -0,0 +1,19 @@ +简单浏览器更新推送的实现 | CC的部落格

    简单浏览器更新推送的实现

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    简单浏览器更新推送的实现这篇文章主要想大家介绍如何使用webpushr及其对应的插件hexo-web-push-notification来帮我们节省时间完成自动推送更新

    插件安装

    npm i hexo-web-push-notification --save

    注册 webpushr 账号

    首先进入官网注册账号 ,注意需要谷歌人机验证,请自备工具访问

    注册后登录就进入网站选择界面,不过新注册应该是直接进入添加新网站,老用户也可点击添加新网站,但实际上可以多网站共用,因此也就没没必要了

    根据图中提示自行完善网站信息

    注册完毕后就可前往管理面板了

    这里截图划线部分为Tracking code,忘记保存的话可以回退步骤,或者待会儿在管理面板查看

    然后我们大致熟悉一下环境,更多信息可自行查看;

    为什么使用这个实际上因为

    1. 他能做到用户主动订阅浏览器更新通知,新文章或者公告等(后面再讲)
    2. 它在 60000 订阅一下是完全免费的,而且很可靠,你不需要服务器或者其他复杂配置,所有一切均由 webpushr 完成
    3. 懒得使用网站统计,它这个可视化的数据也还是够用了,每周也会给你发一封邮件,说明你这周的订阅表现
    4. 它的功能强大,自定义程度高,界面比较友好(定时推送某个公告,用户浏览 N 个页面后弹出订阅通知,小部件配色,位置调整,所有更改在网站更改完毕后将会立即更新,不用更新网站配置等等)

    当然他还是有缺点的

    1. 浏览器清除本地数据后他会把你当作新用户发送欢迎通知,影响了数据统计
    2. 它的地图把宝岛台湾划在中国之外
    3. 有时候你会延后几天收到一条更新通知

    获取几个必要配置

    1. 点击Setup -> Tracking code(或Integration -> Manual Integration),如果你刚才保存了可以核对一下是否有误
    2. 点击Integration -> REST API Keys可以获取到KeyAuthentication Token

    加下来我们进行配置,按照开发者的 README,我们需要在 HEXO 根目录的配置文件_config.yml添加如下内容(记得替换为自己的)

    webPushNotification:
    webpushrKey: "your webpushr rest api key"
    webpushrAuthToken: "your webpushr authorize token"
    trackingCode: "AEGlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLVbjpCw8x2GmFmi1ZcLTz0ni6OnX5MAwoM88"

    关于安装部分就差不多结束了,下面我们回到 webpushr 网站对我们的网站进行相关配置

    这部分就不截图了,大家即使不懂英语也能看明白知道 setup, push 的意思再配合网站的显示,还有操作变化都能明白(网页翻译真好用),比如选择订阅推送的样式内容(emoji 也是特色个人觉得),订阅通知小铃铛,欢迎推送,这些在你刚才打开我网站的时候都已经体验过了(如果没有,检查一下弹窗是否被拦截,清楚浏览器数据后体验一下)

    API 通知就是利用我们生成好的 newPost.json 本地与远端进行比较来进行更新文章推送,比较特色的就是定时自动推送,这个我们拿来做临时公告也是非常方便的

    其他内容就请读者自定探索吧

    如何完成文章更新推送

    但说了这么多,触发推送的条件还没讲呢,而我们一般推送文章,大致使用如下格式即可

    ---
    title: Hexo使用Web Push Notification 浏览器通知推送
    tags:
    - hexo
    - 服务器推送技术
    - push notifications
    categories:
    - 开发
    comments: true
    abbrlink: 98ae9e55
    date: 2020-02-26 10:00:00
    ---

    Web Push Notification 是怎么工作的?个人博客为什么要使用它?如何使用它?

    <!-- more -->

    请注意一定要有预览内容,也就是---<!-- more -->之间的内容

    讲到这里我们就发现,我们可以通过是否写预览内容来自主控制是否向订阅者推送这篇文章更新,而不是所有文章都推送,这种主动方式是我觉得比较人性化的

    点击 查看开发经历** | 查看更多相关资讯 | 特殊推送解决方案 | **泛用推送解决方案

    总结来说就是 hexo g 这个步骤 生成 webpushr-sw.js 和 newPost.json,在 hexo d 这个步骤会对比本地这个 json 中文章 ID 和 你的远程 比如我的博客地址 https://blog.ccknbc.cc/newPost.json 中未更新的 ID,若有不同,则通过 API 触发文章更新推送通知。

    因此即使你和我一样未使用 hexo d 而是使用 Actions 直接到 public 目录下使用 git 推送,还是要加上 hexo d 或者 npm run deploy 命令。

    其他须知

    你如果阅读了隐私,你会发现它可以收集用户的很多信息,比如 IP,国家或地区,设配类型等等,这些你可以选择自行开启或关闭,因为有时候过度收集这些无用隐私也是没必要的;不过作为有垃圾评论或者恶意评论来说,这种记录也是一种帮助

    当然要想让读者愿意订阅你的博客,你的确要在内容下下功夫,我相信只要你能持续输出有趣有用的内容,就不愁没有订阅者的,一起加油吧!

    这篇文章还有许多不足的地方,如有错误,欢迎指正

    后续更新

    如果你的博客和我一样使用多处托管,并且用了二级域名做主页,比如我的 ccknbc.github.io 为我的主页,新建仓库名叫 blog 来作为博客(访问地址即为 ccknbc.github.io/blog),同样 gitee,gitlab 我也是这么做的,我们需要在 yourname.github.io 仓库(对应着你的根域名实际上)上传webpushr提供的webpushr-sw.js文件确保你的根域名可以通过这种方式访问到 domain.com/webpushr-sw.js(举例)

    这样即使咱们 HEXO 配置处这么配置的话(举例),也能正常使用本插件了

    url: https://ccknbc.github.io/blog
    root: /blog/

    也不用演示了,您已经体验过了

    其他平台

    例如https://app.onesignal.com/ https://app.pushengage.com/ https://digitalpush.org/ https://pushwizard.com/ 等等

    都是我推荐的平台,还都不错,配置也都差不多,免费的话各有各的优势,不限额的话我想其实也没啥人订阅吧,这种东西只是折腾罢了

    我配置了 20 个第三方平台,但现实是有多少人愿意浏览器订阅呢,至少在中国,大家普遍讨厌弹窗,把它当作广告,又或者时差问题,个性化问题。

    RSS TO PUSH, RSS TO MAIL 除非我博客真的是优质文章,但谁来订阅呢,随缘吧,反正又不是不能手写 webpush 啊哈哈哈哈,晚安

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/implementation-of-simple-browser-update-push/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/introduction-of-plugin-tags-based-on-butterfly/index.html b/posts/introduction-of-plugin-tags-based-on-butterfly/index.html new file mode 100644 index 000000000..30c24f6dd --- /dev/null +++ b/posts/introduction-of-plugin-tags-based-on-butterfly/index.html @@ -0,0 +1,19 @@ +Hexo标签笔记 | CC的部落格

    Hexo标签笔记

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    CC 的部落格 Hexo 标签笔记 ,其中大部分完整转载至糖果屋店长原文,根据本站实际情况进行了增减,仅保留源码和参数说明部分,若要查看具体效果,可前往

    按钮 Button

    行内

    {% btn '#',# %}
    {% btn '#',#,outline%}

    固定

    {% btn '#',#,far fa-hand-point-right,block larger %}
    {% btn '#',#,far fa-hand-point-right,block center larger %}
    {% btn '#',#,far fa-hand-point-right,block right blue larger %}

    居中多个

    <div class="btn-center">
    {% btn '#',#,far fa-hand-point-right,larger %}
    {% btn '#',#,far fa-hand-point-right,blue larger %}
    {% btn '#',#,far fa-hand-point-right,pink larger %}
    {% btn '#',#,far fa-hand-point-right,red larger %}
    {% btn '#',#,far fa-hand-point-right,purple larger %}
    {% btn '#',#,far fa-hand-point-right,orange larger %}
    {% btn '#',#,far fa-hand-point-right,green larger %}
    </div>
    <div class="btn-center">
    {% btn '#',#,far fa-hand-point-right,outline larger %}
    {% btn '#',#,far fa-hand-point-right,outline blue larger %}
    {% btn '#',#,far fa-hand-point-right,outline pink larger %}
    {% btn '#',#,far fa-hand-point-right,outline red larger %}
    {% btn '#',#,far fa-hand-point-right,outline purple larger %}
    {% btn '#',#,far fa-hand-point-right,outline orange larger %}
    {% btn '#',#,far fa-hand-point-right,outline green larger %}
    </div>

    按钮 btns

    {% btns 样式参数 %}
    {% cell 标题, 链接, 图片或者图标 %}
    {% cell 标题, 链接, 图片或者图标 %}
    {% endbtns %}
    1. 圆角样式:rounded, circle
    2. 增加文字样式:可以在容器内增加 <b>标题</b><p>描述文字</p>
    3. 布局方式:默认为自动宽度,适合视野内只有一两个的情况。
      参数含义
      wide宽一点的按钮
      fill填充布局,自动铺满至少一行,多了会换行
      center居中,按钮之间是固定间距
      around居中分散
      grid2等宽最多 2 列,屏幕变窄会适当减少列数
      grid3等宽最多 3 列,屏幕变窄会适当减少列数
      grid4等宽最多 4 列,屏幕变窄会适当减少列数
      grid5等宽最多 5 列,屏幕变窄会适当减少列数

    行内文本样式 text

    {% u 文本内容 %}
    {% emp 文本内容 %}
    {% wavy 文本内容 %}
    {% del 文本内容 %}
    {% kbd 文本内容 %}
    {% psw 文本内容 %}
    {% label 文本内容 标签颜色 %}
    {% nota 注释词汇 , 悬停显示的注解内容 %}

    行内文本 span

    {% span 样式参数(参数以空格划分), 文本内容 %}
    1. 字体: logo, code
    2. 颜色: red,yellow,green,cyan,blue,gray
    3. 大小: small, h4, h3, h2, h1, large, huge, ultra
    4. 对齐方向: left, center, right
    - 彩色文字
    在一段话中方便插入各种颜色的标签,包括:{% span red, 红色 %}、{% span yellow, 黄色 %}、{% span green, 绿色 %}、{% span cyan, 青色 %}、{% span blue, 蓝色 %}、{% span gray, 灰色 %}。
    - 超大号文字
    文档「开始」页面中的标题部分就是超大号文字。
    {% span center logo large, 康纳百川 %}
    {% span center small, 康纳百川 %}

    段落文本 p

    {% p 样式参数(参数以空格划分), 文本内容 %}
    1. 字体: logo, code
    2. 颜色: red,yellow,green,cyan,blue,gray
    3. 大小: small, h4, h3, h2, h1, large, huge, ultra
    4. 对齐方向: left, center, right
    - 彩色文字
    在一段话中方便插入各种颜色的标签,包括:{% p red, 红色 %}、{% p yellow, 黄色 %}、{% p green, 绿色 %}、{% p cyan, 青色 %}、{% p blue, 蓝色 %}、{% p gray, 灰色 %}。
    - 超大号文字
    文档「开始」页面中的标题部分就是超大号文字。
    {% p center logo large, CC's Blog %}
    {% p center small, CC's Blog %}

    引用 note

    修改主题配置文件

    note:
    # Note tag style values:
    # - simple bs-callout old alert style. Default.
    # - modern bs-callout new (v2-v3) alert style.
    # - flat flat callout style with background, like on Mozilla or StackOverflow.
    # - disabled disable all CSS styles import of note tag.
    style: simple
    icons: false
    border_radius: 3
    # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6).
    # Offset also applied to label tag variables. This option can work with disabled note tag.
    light_bg_offset: 0

    Note标签有两种用法。iconslight_bg_offset只对方法一生效。

    方法一

    {% note [class] [no-icon] [style] %}
    Any content (support inline tags too.io).
    {% endnote %}

    方法二

    {% note [color] [icon] [style] %}
    Any content (support inline tags too.io).
    {% endnote %}

    方法一

    参数用法
    class【可选】标识,不同的标识有不同的配色
    ( default / primary / success / info / warning / danger )
    no-icon【可选】不显示 icon
    style【可选】可以覆盖配置中的 style
    (simple/modern/flat/disabled)

    方法二

    参数用法
    class【可选】标识,不同的标识有不同的配色
    ( default / primary / success / info / warning / danger )
    no-icon【可选】可配置自定义 icon (只支持 fontawesome 图标, 也可以配置 no-icon )
    style【可选】可以覆盖配置中的 style
    (simple/modern/flat/disabled)

    方法一

    1. simple样式
    {% note simple %}默认 提示块标签{% endnote %}

    {% note default simple %}default 提示块标签{% endnote %}

    {% note primary simple %}primary 提示块标签{% endnote %}

    {% note success simple %}success 提示块标签{% endnote %}

    {% note info simple %}info 提示块标签{% endnote %}

    {% note warning simple %}warning 提示块标签{% endnote %}

    {% note danger simple %}danger 提示块标签{% endnote %}
    1. modern样式
    {% note modern %}默认 提示块标签{% endnote %}

    {% note default modern %}default 提示块标签{% endnote %}

    {% note primary modern %}primary 提示块标签{% endnote %}

    {% note success modern %}success 提示块标签{% endnote %}

    {% note info modern %}info 提示块标签{% endnote %}

    {% note warning modern %}warning 提示块标签{% endnote %}

    {% note danger modern %}danger 提示块标签{% endnote %}
    1. flat样式
    {% note flat %}默认 提示块标签{% endnote %}

    {% note default flat %}default 提示块标签{% endnote %}

    {% note primary flat %}primary 提示块标签{% endnote %}

    {% note success flat %}success 提示块标签{% endnote %}

    {% note info flat %}info 提示块标签{% endnote %}

    {% note warning flat %}warning 提示块标签{% endnote %}

    {% note danger flat %}danger 提示块标签{% endnote %}
    1. disabled样式
    {% note disabled %}默认 提示块标签{% endnote %}

    {% note default disabled %}default 提示块标签{% endnote %}

    {% note primary disabled %}primary 提示块标签{% endnote %}

    {% note success disabled %}success 提示块标签{% endnote %}

    {% note info disabled %}info 提示块标签{% endnote %}

    {% note warning disabled %}warning 提示块标签{% endnote %}

    {% note danger disabled %}danger 提示块标签{% endnote %}
    1. no-icon样式
    {% note no-icon %}默认 提示块标签{% endnote %}

    {% note default no-icon %}default 提示块标签{% endnote %}

    {% note primary no-icon %}primary 提示块标签{% endnote %}

    {% note success no-icon %}success 提示块标签{% endnote %}

    {% note info no-icon %}info 提示块标签{% endnote %}

    {% note warning no-icon %}warning 提示块标签{% endnote %}

    {% note danger no-icon %}danger 提示块标签{% endnote %}

    方法二

    1. simple样式
    {% note 'fab fa-cc-visa' simple %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note blue 'fas fa-bullhorn' simple %}2021 年快到了....{% endnote %}

    {% note pink 'fas fa-car-crash' simple %}小心开车 安全至上{% endnote %}

    {% note red 'fas fa-fan' simple%}这是三片呢?还是四片?{% endnote %}

    {% note orange 'fas fa-battery-half' simple %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note purple 'far fa-hand-scissors' simple %}剪刀石头布{% endnote %}

    {% note green 'fab fa-internet-explorer' simple %}前端最讨厌的浏览器{% endnote %}
    1. modern样式
    {% note 'fab fa-cc-visa' modern %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note blue 'fas fa-bullhorn' modern %}2021 年快到了....{% endnote %}

    {% note pink 'fas fa-car-crash' modern %}小心开车 安全至上{% endnote %}

    {% note red 'fas fa-fan' modern%}这是三片呢?还是四片?{% endnote %}

    {% note orange 'fas fa-battery-half' modern %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note purple 'far fa-hand-scissors' modern %}剪刀石头布{% endnote %}

    {% note green 'fab fa-internet-explorer' modern %}前端最讨厌的浏览器{% endnote %}
    1. flat样式
    {% note 'fab fa-cc-visa' flat %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note blue 'fas fa-bullhorn' flat %}2021 年快到了....{% endnote %}

    {% note pink 'fas fa-car-crash' flat %}小心开车 安全至上{% endnote %}

    {% note red 'fas fa-fan' flat%}这是三片呢?还是四片?{% endnote %}

    {% note orange 'fas fa-battery-half' flat %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note purple 'far fa-hand-scissors' flat %}剪刀石头布{% endnote %}

    {% note green 'fab fa-internet-explorer' flat %}前端最讨厌的浏览器{% endnote %}
    1. disabled样式
    {% note 'fab fa-cc-visa' disabled %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note blue 'fas fa-bullhorn' disabled %}2021 年快到了....{% endnote %}

    {% note pink 'fas fa-car-crash' disabled %}小心开车 安全至上{% endnote %}

    {% note red 'fas fa-fan' disabled %}这是三片呢?还是四片?{% endnote %}

    {% note orange 'fas fa-battery-half' disabled %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note purple 'far fa-hand-scissors' disabled %}剪刀石头布{% endnote %}

    {% note green 'fab fa-internet-explorer' disabled %}前端最讨厌的浏览器{% endnote %}
    1. no-icon样式
    {% note no-icon %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note blue no-icon %}2021 年快到了....{% endnote %}

    {% note pink no-icon %}小心开车 安全至上{% endnote %}

    {% note red no-icon %}这是三片呢?还是四片?{% endnote %}

    {% note orange no-icon %}你是刷 Visa 还是 UnionPay{% endnote %}

    {% note purple no-icon %}剪刀石头布{% endnote %}

    {% note green no-icon %}前端最讨厌的浏览器{% endnote %}

    上标标签 tip

    主要样式参考自小康的 butterfly 渐变背景标签,自己写了个tip.js来渲染标签,精简了一下代码。

    {% tip [参数,可选] %}文本内容{% endtip %}
    1. 样式: success,error,warning,bolt,ban,home,sync,cogs,key,bell
    2. 自定义图标: 支持 fontawesome。
    {% tip %}默认情况{% endtip %}
    {% tip success %}success{% endtip %}
    {% tip error %}error{% endtip %}
    {% tip warning %}warning{% endtip %}
    {% tip bolt %}bolt{% endtip %}
    {% tip ban %}ban{% endtip %}
    {% tip home %}home{% endtip %}
    {% tip sync %}sync{% endtip %}
    {% tip cogs %}cogs{% endtip %}
    {% tip key %}key{% endtip %}
    {% tip bell %}bell{% endtip %}
    {% tip fa-atom %}自定义 font awesome 图标{% endtip %}

    动态标签 anima

    {% tip [参数,可选] %}文本内容{% endtip %}

    更多详情请参看font-awesome-animation 文档

    1. 将所需的 CSS 类添加到图标(或 DOM 中的任何元素)。
    2. 对于父级悬停样式,需要给目标元素添加指定 CSS 类,同时还要给目标元素的父级元素添加 CSS 类faa-parent animated-hover。(详情见示例及示例源码) You can regulate the speed of the animation by adding the CSS class or . faa-fastfaa-slow
    3. 可以通过给目标元素添加 CSS 类faa-fastfaa-slow来控制动画快慢。
    On DOM load
    当页面加载时
    显示动画
    On hover
    当鼠标悬停时
    显示动画
    On parent hover
    当鼠标悬停
    在父级元素时
    显示动画
     faa-wrench animated faa-wrench animated-hover faa-wrench
     faa-ring animated faa-ring animated-hover faa-ring
     faa-horizontal animated faa-horizontal animated-hover faa-horizontal
     faa-vertical animated faa-vertical animated-hover faa-vertical
     faa-flash animated faa-flash animated-hover faa-flash
     faa-bounce animated faa-bounce animated-hover faa-bounce
     faa-spin animated faa-spin animated-hover faa-spin
     faa-tada animated faa-tada animated-hover faa-tada
     faa-pulse animated faa-pulse animated-hover faa-pulse
     faa-shake animated faa-shake animated-hover faa-shake
     faa-tada animated faa-tada animated-hover faa-tada
     faa-passing animated faa-passing animated-hover faa-passing
     faa-passing-reverse animated faa-passing-reverse animated-hover faa-passing-reverse
     faa-burst animated faa-burst animated-hover faa-burst
     faa-falling animated faa-falling animated-hover faa-falling
     faa-rising animated faa-rising animated-hover faa-rising
    1. On DOM load(当页面加载时显示动画)
    {% tip warning faa-horizontal animated %}warning{% endtip %}
    {% tip ban faa-flash animated %}ban{% endtip %}
    1. 调整动画速度
    {% tip warning faa-horizontal animated faa-fast %}warning{% endtip %}
    {% tip ban faa-flash animated faa-slow %}ban{% endtip %}
    1. On hover(当鼠标悬停时显示动画)
    {% tip warning faa-horizontal animated-hover %}warning{% endtip %}
    {% tip ban faa-flash animated-hover %}ban{% endtip %}
    1. On parent hover(当鼠标悬停在父级元素时显示动画)
    {% tip warning faa-parent animated-hover %}<p class="faa-horizontal">warning</p>{% endtip %}
    {% tip ban faa-parent animated-hover %}<p class="faa-flash">ban</p>{% endtip %}

    单选列表 radio

    {% radio 样式参数(可选), 文本(支持简单md) %}
    1. 颜色: red,yellow,green,cyan,blue,gray
    2. 选中状态: checked
    {% radio 纯文本测试 %}
    {% radio checked, 支持简单的 [markdown](https://guides.github.com/features/mastering-markdown/) 语法 %}
    {% radio red, 支持自定义颜色 %}
    {% radio green, 绿色 %}
    {% radio yellow, 黄色 %}
    {% radio cyan, 青色 %}
    {% radio blue, 蓝色 %}

    复选列表 checkbox

    {% checkbox 样式参数(可选), 文本(支持简单md) %}
    1. 样式: plus, minus, times
    2. 颜色: red,yellow,green,cyan,blue,gray
    3. 选中状态: checked
    {% checkbox 纯文本测试 %}
    {% checkbox checked, 支持简单的 [markdown](https://guides.github.com/features/mastering-markdown/) 语法 %}
    {% checkbox red, 支持自定义颜色 %}
    {% checkbox green checked, 绿色 + 默认选中 %}
    {% checkbox yellow checked, 黄色 + 默认选中 %}
    {% checkbox cyan checked, 青色 + 默认选中 %}
    {% checkbox blue checked, 蓝色 + 默认选中 %}
    {% checkbox plus green checked, 增加 %}
    {% checkbox minus yellow checked, 减少 %}
    {% checkbox times red checked, 叉 %}

    时间轴 timeline

    {% timeline 时间线标题(可选) %}
    {% timenode 时间节点(标题) %}
    正文内容
    {% endtimenode %}
    {% timenode 时间节点(标题) %}
    正文内容
    {% endtimenode %}
    {% endtimeline %}
    {% link 标题, 链接, 图片链接(可选) %}

    github 卡片 ghcard

    ghcard 使用了github-readme-stats的 API,支持直接使用 markdown 语法来写。

    {% ghcard 用户名, 其它参数(可选) %}
    {% ghcard 用户名/仓库, 其它参数(可选) %}

    更多参数可以参考:

    使用,分割各个参数。写法为:参数名=参数值以下只写几个常用参数值。

    参数名取值释义
    hidestars,commits,prs,issues,contribs隐藏指定统计
    count_privatetrue将私人项目贡献添加到总提交计数中
    show_iconstrue显示图标
    theme请查阅 Available Themes主题
    1. 用户信息卡片
    | {% ghcard ccknbc %}                | {% ghcard ccknbc, theme=vue %}             |
    | ---------------------------------- | ------------------------------------------ |
    | {% ghcard ccknbc, theme=buefy %} | {% ghcard ccknbc, theme=solarized-light %} |
    | {% ghcard ccknbc, theme=onedark %} | {% ghcard ccknbc, theme=solarized-dark %} |
    | {% ghcard ccknbc, theme=algolia %} | {% ghcard ccknbc, theme=calm %} |
    1. 仓库信息卡片
    | {% ghcard ccknbc-actions/blogroll %}                | {% ghcard ccknbc-actions/blogroll, theme=vue %}             |
    | --------------------------------------------------- | ----------------------------------------------------------- |
    | {% ghcard ccknbc-actions/blogroll, theme=buefy %} | {% ghcard ccknbc-actions/blogroll, theme=solarized-light %} |
    | {% ghcard ccknbc-actions/blogroll, theme=onedark %} | {% ghcard ccknbc-actions/blogroll, theme=solarized-dark %} |
    | {% ghcard ccknbc-actions/blogroll, theme=algolia %} | {% ghcard ccknbc-actions/blogroll, theme=calm %} |

    github 徽标 ghbdage

    关于 ghbdage 参数的更多具体用法可以参看糖果屋教程:添加 github 徽标

    {% bdage [right],[left],[logo]||[color],[link],[title]||[option] %}
    1. left:徽标左边的信息,必选参数。
    2. right: 徽标右边的信息,必选参数,
    3. logo:徽标图标,图标名称详见simpleicons,可选参数。
    4. color:徽标右边的颜色,可选参数。
    5. link:指向的链接,可选参数。
    6. title:徽标的额外信息,可选参数。主要用于优化 SEO,但object标签不会像a标签一样在鼠标悬停显示title信息。
    7. option:自定义参数,支持shields.io的全部 API 参数支持,具体参数可以参看上文中的拓展写法示例。形式为name1=value2&name2=value2

    本标签的参数分为三组,用||分割。

    1. 基本参数,定义徽标左右文字和图标
    {% bdage Theme,Butterfly %}
    {% bdage Frame,Hexo,hexo %}
    1. 信息参数,定义徽标右侧内容背景色,指向链接
    {% bdage CDN,JsDelivr,jsDelivr||abcdef,https://metroui.org.ua/index.html,本站使用JsDelivr为静态资源提供CDN加速 %}
    //如果是跨顺序省略可选参数,仍然需要写个逗号,用作分割
    {% bdage Source,GitHub,GitHub||,https://github.com/ %}
    1. 拓展参数,支持 shields 的 API 的全部参数内容
    {% bdage Hosted,Vercel,Vercel||brightgreen,https://vercel.com/,本站采用双线部署,默认线路托管于Vercel||style=social&logoWidth=20 %}
    //如果是跨顺序省略可选参数组,仍然需要写双竖线||用作分割
    {% bdage Hosted,Vercel,Vercel||||style=social&logoWidth=20&logoColor=violet %}

    网站卡片 sites

    {% sitegroup %}
    {% site 标题, url=链接, screenshot=截图链接, avatar=头像链接(可选), description=描述(可选) %}
    {% site 标题, url=链接, screenshot=截图链接, avatar=头像链接(可选), description=描述(可选) %}
    {% endsitegroup %}

    行内图片 inlineimage

    {% inlineimage 图片链接, height=高度(可选) %}

    高度:height=**px

    单张图片 image

    {% image 链接, width=宽度(可选), height=高度(可选), alt=描述(可选), bg=占位颜色(可选) %}
    1. 图片宽度高度:width=300px, height=32px
    2. 图片描述:alt=图片描述(butterfly 需要在主题配置文件中开启图片描述)
    3. 占位背景色:bg=#f2f2f2

    音频 audio

    {% audio 音频链接 %}

    视频 video

    {% video 视频链接 %}
    1. 对其方向:left, center, right
    2. 列数:逗号后面直接写列数,支持 1 ~ 4 列。
    3. 100%宽度
    {% video https://file.nmb.show/down.php/86c301fbc6183f50fb0487e13e5a1f64.mp4 %}
    1. 50%宽度
    {% videos, 2 %}

    ......

    {% endvideos %}
    1. 25%宽度
    {% videos, 4 %}

    ......

    {% endvideos %}
    1. gallerygroup 相册图库
    <div class="gallery-group-main">
    {% galleryGroup name description link img-url %}
    {% galleryGroup name description link img-url %}
    {% galleryGroup name description link img-url %}
    </div>
    1. gallery 相册
    {% gallery %}
    markdown 圖片格式
    {% endgallery %}
    1. gallerygroup 相册图库

      思维拓展一下,相册图库的实质其实就是个快捷方式,可以自定义添加描述、封面、链接。那么我们未必要把它当做一个相册,完全可以作为一个链接卡片,链接到视频、QQ、友链都是不错的选择。

      参数名释义
      name图库名字
      description图库描述
      link链接到对应相册的地址
      img-url图库封面
    2. gallery 相册区别于旧版的 Gallery 相册,新的 Gallery 相册会自动根据图片长度进行排版,书写也更加方便,与 markdown 格式一样。可根据需要插入到相应的 md。无需再自己配置长宽。建议在粘贴时故意使用长短、大小、横竖不一的图片,会有更好的效果。(尺寸完全相同的图片只会平铺输出,效果很糟糕)

    隐藏折叠 tag-hide

    hide-inline

    {% hideInline 描述,按钮颜色,字体颜色 %}
    {% hideInline 描述 %}

    hide-block

    {% hideBlock 描述 %}

    ......

    {% endhideBlock %}

    hide-toggle

    {% hideToggle 描述 %}

    ......

    {% endhideToggle %}

    折叠框 folding

    {% folding 参数(可选), 标题 %}
    ![](https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg)
    {% endfolding %}
    1. 颜色:blue, cyan, green, yellow, red
    2. 状态:状态填写 open 代表默认打开。

    分栏 tab

    {% tabs Unique name, [index] %}

    <!-- tab [Tab caption] [@icon] -->

    Any content (support inline tags too).

    <!-- endtab -->

    {% endtabs %}
    1. Unique name :

      • 选项卡块标签的唯一名称,不带逗号。
      • 将在#id 中用作每个标签及其索引号的前缀。
      • 如果名称中包含空格,则对于生成#id,所有空格将由破折号代替。
      • 仅当前帖子/页面的 URL 必须是唯一的!
    2. [index]:

      • 活动选项卡的索引号。
      • 如果未指定,将选择第一个标签(1)。
      • 如果 index 为-1,则不会选择任何选项卡。
      • 可选参数。
    3. [Tab caption]:

      • 当前选项卡的标题。
      • 如果未指定标题,则带有制表符索引后缀的唯一名称将用作制表符的标题。
      • 如果未指定标题,但指定了图标,则标题将为空。
      • 可选参数。
    4. [@icon]:

      • FontAwesome 图标名称(全名,看起来像“ fas fa-font”)
      • 可以指定带空格或不带空格;
      • 例如’Tab caption @icon’ 和 ‘Tab caption@icon’.
      • 可选参数。

    嵌套

    {% subtabs name %}

    ......

    {% endsubtabs %}

    数据集合 issues

    {% issues type | api=url | group=key:value1,value2(可选) %}

    type(类型) 根据需求不同,会将 issues 内容解析成不同的 HTML 标签,目前支持的类型有:

    1. 时间轴timeline: 解析成timeline标签,issue的标题对应timeline的时间,issue的内容对应timeline的内容。
    2. 网站卡片sites: 解析成sites标签,需要有JSON代码块,各参数对应sites标签参数:
    {
    "title": "",
    "screenshot": "",
    "url": "",
    "avatar": "",
    "description": "",
    "「keywords」": ""
    }
    参数释义
    title网站名称
    screenshot网站预览图
    url网站链接,需要添加

    ``https://协议组成完整域名。否则可能被识别成站点相对路径。 | | avatar | 站长头像 | | 「keywords」 | 分组依据,未必要叫「keywords」,详见下文 group(分组) |

    api(接口) url 为可以调的通的 API,例如:

    api=https://gitee.com/api/v5/repos/xaoxuu/friends/issues?sort=updated&state=open&page=1&per_page=100&labels=active
    api=https://api.github.com/repos/xaoxuu/friends/issues?sort=updated&state=open&page=1&per_page=100&labels=active
    参数释义
    https://gitee.com/api/v5/gitee 仓库的 api
    https://api.github.com/github 仓库的 api
    repos/xaoxuu/friends/issuesrepos/用户名/仓库名/issues
    sort=updated&state=open界定哪些类型的``issues 会
    被读取过来渲染成相应的标签
    page=1&per_page=100读取前 100 条 issues
    labels=active控制默认的 issue 不显示,

    只有自己审核通过添加了 active 标签之后才会显示 |

    group(分组) sites类型的issues默认不分组,如果需要分组,可指定分组依据「keywords」,和分组白名单「value1」「value2」等,例如:

    group=version:v4,v3,v2
    # 此处的version就是上文中的「keywords」

    这个参数的作用就是,筛选出JSON中包含"version": "v4"或者"version":"v3"或者"version": "v2"的数据,并分组显示。

    仓库 ISSUES 模板配置

    因本主题已去 jquery 化(我也不想要,这个标签也不怎么用,不过那个时间线可以用来发说说什么的),所以为了正常显示需要先引入相关依赖,这里不再演示,请直接查看源码即可

    <script defer src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@latest/source/js/issues.min.js"></script>
    • 时间轴标签timeline渲染
    {% issues timeline | api=https://gitee.com/api/v5/repos/xaoxuu/timeline/issues?state=open&creator=xaoxuu&sort=created&direction=desc&page=1&per_page=100 %}
    • 网站卡片标签sites渲染
      • gitee 仓库示例
    {% issues sites | api=https://gitee.com/api/v5/repos/xaoxuu/friends/issues?sort=updated&state=open&page=1&per_page=100&labels=active %}
    • github 仓库示例
    {% issues sites | api=https://api.github.com/repos/xaoxuu/friends/issues?sort=updated&state=open&page=1&per_page=100&labels=active %}
    • 网站卡片标签sites分组渲染这是Volantis主题官网的「示例博客」页面的数据:
    {% issues sites | api=https://api.github.com/repos/volantis-x/examples/issues?sort=updated&state=open&page=1&per_page=100 | group=version:版本:^4.0,版本:^3.0,版本:^2.0 %}

    诗词标签 poem

    {% poem [title],[author] %}
    诗词内容
    {% endpoem %}

    进度条 progress

    进度条标签参考沂佰孜猫-给 HEXO 文章添加彩色进度条。源样式提取自Cuteen主题。

    {% progress [width] [color] [text] %}
    1. width: 0 到 100 的阿拉伯数字
    2. color: 颜色,取值有red,yellow,green,cyan,blue,gray
    3. text:进度条上的文字内容

    mermaid

    {% mermaid %}
    pie
    title Key elements in Product X
    "Calcium" : 42.96
    "Potassium" : 50.05
    "Magnesium" : 10.01
    "Iron" : 5
    {% endmermaid %}

    {% mermaid %}
    gantt
    title A Gantt Diagram
    dateFormat YYYY-MM-DD
    section Section
    A task :a1, 2014-01-01, 30d
    Another task :after a1 , 20d
    section Another
    Task in sec :2014-01-12 , 12d
    another task : 24d
    {% endmermaid %}

    {% mermaid %}
    gantt
    title A Gantt Diagram
    dateFormat YYYY-MM-DD
    section Section
    A task :a1, 2014-01-01, 30d
    Another task :after a1 , 20d
    section Another
    Task in sec :2014-01-12 , 12d
    another task : 24d
    {% endmermaid %}

    动态图表 chartjs

    {% chart 90% 300 %}
    {
    type: 'line',
    data: {
    labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
    datasets: [{
    label: 'My First dataset',
    backgroundColor: 'rgb(255, 99, 132)',
    borderColor: 'rgb(255, 99, 132)',
    data: [0, 10, 5, 2, 20, 30, 45]
    }]
    },
    options: {
    responsive: true,
    title: {
    display: true,
    text: 'Chart.js Line Chart'
    }
    }
    }
    {% endchart %}

    关于预览,更多详细内容,请分别前往 插件文档 | 原文档 查看

    媒体 mmedia

    简介

    hexo-tag-mmedia 是一个能在 Hexo 中快速插入媒体标签的插件,目前支持的标签和平台有(持续开发中):

    DEMO

    [http://demo.hexo-tag-mmedia.u2sb.com/](http://demo.hexo-tag-mmedia.u2sb.com/](http://demo.hexo-tag-mmedia.u2sb.com/))

    使用

    hexo-tag-mmedia 插件和其他 hexo 插件使用方法类似,诸如 如何启用一个插件 之类的共性问题就不再赘述了,只说 hexo-tag-mmedia 相关的。

    安装

    npm install hexo-tag-mmedia@1 --save
    pnpm install hexo-tag-mmedia@1 --save
    yarn add hexo-tag-mmedia@1 --save

    配置

    如需修改配置,请务必不要保留空选项,空选项会覆盖默认配置,严重可能直接导致插件无法使用。

    单项使用的文档中会详细讲解对应的使用文档,请自行阅读后再做配置。

    下面只是示例,请勿全盘复制,请看清后面的讲解后组织自己的配置文件。

    持续更新中,详情见详细文档和 源码](https://github.com/u2sb/hexo-tag-mmedia/blob/1.x/src/config/config_default.yml))

    mmedia:
    audio:
    default:
    video:
    default:
    aplayer:
    js: [https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.js](https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.js)
    css: [https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.css](https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.css)
    default:
    contents:
    meting:
    js: [https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js](https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js)
    api:
    default:
    dplayer:
    js: [https://cdn.jsdelivr.net/npm/dplayer@1/dist/DPlayer.min.js](https://cdn.jsdelivr.net/npm/dplayer@1/dist/DPlayer.min.js)
    hls_js: [https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js](https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js)
    dash_js: [https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js](https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js)
    shaka_dash_js: [https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js](https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js)
    flv_js: [https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js](https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js)
    webtorrent_js: [https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js](https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js)
    default:
    contents:
    bilibili:
    default:
    page: 1
    danmaku: true
    allowfullscreen: allowfullscreen
    sandbox: allow-top-navigation allow-same-origin allow-forms allow-scripts allow-popups
    width: 100%
    max_width: 850px
    margin: auto
    xigua:
    default:
    autoplay: false
    startTime: 0
    allowfullscreen: allowfullscreen
    sandbox: allow-top-navigation allow-same-origin allow-forms allow-scripts allow-popups
    width: 100%
    max_width: 850px
    margin: auto

    解释

    • 配置项较多目的是给予最大的自定义权限,默认情况下不做配置也可以使用。
    • 配置文件放在博客根目录的 _config.yml
    • default 为默认配置,在 _config.yml 中填写就不需要在每个标签全部写入了,所有允许在 mmedia 标签上写入的配置项,均可在 default 下配置。
    • default 下 contents 项,用于设置 JSON 类型的默认配置,注意要使用 yaml 格式写默认配置,以下是几个示例。

    示例

    如无法读懂下面的示例,请阅读后面的文档后再回来看。

    修改 Aplayer 的 js 文件:

    mmedia:
    aplayer:
    js: [https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js](https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js)
    css: [https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css](https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css)

    将 Aplayer 的 JS 和 CSS 放入博客目录:

    首先请下载 APlayer.min.jsAPlayer.min.js 文件,放入博客下 source/assets/js/source/assets/css/ 下(路径只是示例)

    mmedia:
    aplayer:
    js: /assets/js/APlayer.min.js
    css: /assets/css/APlayer.min.css

    Meting 修改循环方式为随机循环:

    mmedia:
    meting:
    default:
    loop: all
    order: random

    Dplayer 修改弹幕 API:

    mmedia:
    dplayer:
    default:
    contents:
    danmaku:
    api: [https://api.prprpr.me/dplayer/v3/](https://api.prprpr.me/dplayer/v3/)

    使用

    下面只是快速示例,请阅读后面的文档后再回来看。示例只是为了展示配置方式瞎写的,一些配置不一定正确,不要照抄。

    {% mmedia "audio" "src:a.mp3" %}
    {% mmedia "aplayer" "name:songName" "url:a.mp3" %}
    {% mmedia "meting" "auto=[https://y.qq.com/n/yqq/song/001RGrEX3ija5X.html"](https://y.qq.com/n/yqq/song/001RGrEX3ija5X.html") %}
    {% mmedia "bilibili" "bvid:BV1hb4y1R7xf" %}
    {% mmedia "xigua" "xid=6925997698269053453" %}
    {% mmedias "dplayer" "flv:" "url:[https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4"](https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4") %}
    {
    "contextmenu":
    [
    {
    text: "custom1",
    link: "[https://github.com/DIYgod/DPlayer"](https://github.com/DIYgod/DPlayer")
    }
    ]
    }
    {% endmmedias %}
    {% mmedias "aplayer" "autoplay:false" %}
    {
    "volume": 0.8,
    "audio":
    [
    {
    "name": "name1",
    "artist": "artist1",
    "url": "url1.mp3",
    "cover": "cover1.jpg",
    "lrc": "lrc1.lrc",
    "theme": "#ebd0c2"
    },
    {
    "name": "name2",
    "artist": "artist2",
    "url": "url2.mp3",
    "cover": "cover2.jpg",
    "lrc": "lrc2.lrc",
    "theme": "#46718b"
    }
    ]
    }
    {% endmmedias %}

    markdown 内可以使用两种标签作为插件,分别是 mmediammedias,使用方式为:

    {% mmedia %}
    {% mmedias %}
    {% endmmedias %}

    只使用 args 作为传参方式时,两种标签均可使用,当需要使用 contents 传参时,只能使用 mmedias

    后面第一个参数用于标记标签,可选(以详细文档为主,持续更新中):

    audio video meting aplayer dplayer bilibili xigua

    再后面的参数将直接作为 args 参数直接传入插件。

    参数

    传入标签的参数可以写入到三个位置,分别为:_config.ymlargscontents,其中只有部分插件可使用 contents 配置,具体看详细文档,如有冲突项,覆盖规则为(后面的会被前面发覆盖):

    contents -> args -> _config.yml -> 插件默认

    写入到 args 上的参数,有两种写法,分别是使用 := 分割,两种写法是等效的,在遇到第一个 := 时会自动分割,例如:

    {% mmedia "bilibili" "bvid:BV1hb4y1R7xf" %}

    {% mmedia "bilibili" "bvid=BV1hb4y1R7xf" %}

    两种写法是等效的。

    如果遇到布尔类型的参数,可以简写

    {% mmedia "audio" "src:a.mp3" "autoplay:" %}
    {% mmedia "audio" "src:a.mp3" "autoplay:true" %}

    两种写法等效,但需要注意,:= 一定不能省略。

    JSON 传参

    支持 JSON 方式传参,其中 JSON 为 JSON5](https://json5.org/)) 规范。

    示例:

    {% mmedias "aplayer" "autoplay:false" %}
    {
    "volume": 0.8,
    "audio":
    [
    {
    "name": "name1",
    "artist": "artist1",
    "url": "url1.mp3",
    "cover": "cover1.jpg",
    "lrc": "lrc1.lrc",
    "theme": "#ebd0c2"
    },
    {
    "name": "name2",
    "artist": "artist2",
    "url": "url2.mp3",
    "cover": "cover2.jpg",
    "lrc": "lrc2.lrc",
    "theme": "#46718b"
    }
    ]
    }
    {% endmmedias %}

    从 0.x 升级

    考虑到一部分用户 0.x 版本使用时间较长,迁移成本较高,遂将 0.x 单独发布为一个包,可以用 1.x 版本同时安装。

    详情见 0.X 版本

    虽然能兼容使用,但建议及时修改文章到 1.x ,0.x 版本已不再继续维护。

    开发者要说的几句话

    1. 这个插件并不完美,如果使用中遇到问题,请熟读文档,如果还是有问题,请再读一遍文档,还是有问题,请向开发者反馈。
    2. 关于 JS 重复请求,请升级客户端浏览器版本,两个一样的 JS,只会请求一次,暂时没有想到什么好的办法,如果有,请及时告诉 Aki 。
    3. 关于 pjax,这东西真的不想去做兼容(其实也不难),如果以后闲得无聊的话,可能会做,但不要催 Aki 关于 pjax 兼容的问题。
    4. 不要局限于示例,放开手脚,大胆去尝试,这个插件的开放性真的非常的大。

    介绍

    可以插入 html5 原生 audio 标签

    使用

    {% mmedia "audio" "src:a.mp3" %}
    {% mmedia "audio" "src:[https://baidu.com/a.mp3"](https://baidu.com/a.mp3") "autoplay:true" %}

    参数

    此部分请熟读 Audio 相关介绍](https://www.w3.org/TR/2014/REC-html5-20141028/embedded-content-0.html#the-audio-element))

    • 使用 := 分割。
    • 所有 <audio> 标签的原生参数均可添加,只要能写进去就可以。
    • 具体能否实现相关标准,取决于客户端浏览器。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,使用 JSON5 标准。

    配置

    默认配置可写入 _config.yml

    mmedia:
    audio:
    default:
    autoplay: true
    key: vaule

    介绍

    可以插入 html5 原生 video 标签

    使用

    {% mmedia "video" "src:a.mp4" %}
    {% mmedia "video" "src:[https://baidu.com/a.mp4"](https://baidu.com/a.mp4") "autoplay:true" %}

    参数

    此部分请熟读 Video 相关介绍](https://www.w3.org/TR/2014/REC-html5-20141028/embedded-content-0.html#the-video-element))

    • 使用 := 分割。
    • 所有 <video> 标签的原生参数均可添加,只要能写进去就可以。
    • 具体能否实现相关标准,取决于客户端浏览器。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,使用 JSON5 标准。

    配置

    默认配置可写入 _config.yml

    mmedia:
    video:
    default:
    autoplay: true
    key: vaule

    介绍

    可以插入 MetingJS](https://github.com/metowolf/MetingJS)) 标签。

    使用

    {% mmedia "meting" "auto=[https://y.qq.com/n/yqq/song/001RGrEX3ija5X.html"](https://y.qq.com/n/yqq/song/001RGrEX3ija5X.html") %}
    {% mmedia "meting" "server=netease"	"type=playlist"	"id=60198" %}

    参数

    此部分请熟读 MetingJS 文档](https://github.com/metowolf/MetingJS#option))

    • 使用 := 分割。
    • 所有 <meting-js> 标签的参数均可添加,只要能写进去就可以。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,使用 JSON5 标准。

    {% mmedias "meting" "server=netease" %}
    {
    type:"playlist",
    id:"60198"
    }
    {% endmmedias %}

    配置

    默认配置可写入 _config.yml

    mmedia:
    meting:
    js: [https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js](https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js)
    api: [http://example.com/api.php](http://example.com/api.php)
    default:
    key: vaule

    介绍

    可以插入 aplayer 标签

    使用

    {% mmedia "aplayer" "name:songName" "url:a.mp3" %}
    {% mmedias "aplayer" "autoplay:false" %}
    {
    "volume": 0.8,
    "audio":
    [
    {
    "name": "name1",
    "artist": "artist1",
    "url": "url1.mp3",
    "cover": "cover1.jpg",
    "lrc": "lrc1.lrc",
    "theme": "#ebd0c2"
    },
    {
    "name": "name2",
    "artist": "artist2",
    "url": "url2.mp3",
    "cover": "cover2.jpg",
    "lrc": "lrc2.lrc",
    "theme": "#46718b"
    }
    ]
    }
    {% endmmedias %}

    参数

    此部分请熟读 APlayer 文档](http://aplayer.js.org/))

    • 使用 := 分割。

    详细参数表:

    参数默认解释
    name-audio name
    artist-audio artist
    url-audio url
    cover-audio cover
    lrc-audio lrc
    theme-audio theme
    typeautoaudio type 可选 ‘auto’, ‘hls’, ‘normal’
    autoplayfalseautoplay
    loop‘all’player loop play, values: ‘all’, ‘one’, ‘none’
    order‘list’player play order, values: ‘list’, ‘random’
    volume0.7default volume,
    tlistMaxHeight-list max height

    不在表格内的参数请使用下面 JSON 类型的参数。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,由于允许使用 JSON5,此项配置几乎与 APlayer 完全一致。

    详情请见上方示例。

    配置

    默认配置可写入 _config.yml

    mmedia:
    aplayer:
    js: [https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.js](https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.js)
    css: [https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.css](https://cdn.jsdelivr.net/npm/aplayer@1/dist/APlayer.min.css)
    default:
    contents:

    介绍

    可以插入 dplayer 标签。

    使用

    {% mmedia "dplayer" "url:a.mp4" %}
    {% mmedias "dplayer" "flv:" "url:[https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4"](https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4") %}
    {
    "contextmenu":
    [
    {
    text: "custom1",
    link: "[https://github.com/DIYgod/DPlayer"](https://github.com/DIYgod/DPlayer")
    }
    ]
    }
    {% endmmedias %}

    参数

    此部分请熟读 DPlayer 文档](http://dplayer.js.org/))

    • 使用 := 分割。

    详细参数表:

    参数默认解释
    url-video.url
    pic-video.pic
    thumbnails-video.thumbnails
    typeautovideo.type, values: ‘auto’, ‘hls’, ‘flv’, ‘dash’, ‘webtorrent’, ‘normal’ or other
    autoplayfalsevideo autoplay
    loopfalsevideo loop
    logo-showing logo in the top left corner, you can adjust its size and position by CSS
    volume0.7default volume
    screenshotfalseenable screenshot, if true, video and video poster must enable Cross-Origin
    id-danmaku.id, danmaku pool id, it must be unique
    api-danmaku.api, see Danmaku API](http://dplayer.js.org/guide.html#danmaku-api))

    上面有一个比较特殊的参数 flv,这里单独解释一下,这个参数是用于引入其他 js 文件的,目前支持的有:hls dash shaka_dash flv webtorrent,上述参数可多个一起使用,如果后面带有 js 地址,将直接使用,否则将使用 _config.yml 配置或插件默认配置,如:

    {% mmedia "dplayer" "flv:" "url:a.flv" %}
    {% mmedias "dplayer" "flv:" "hls:[https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"](https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js") %}
    {
    video:
    {
    quality:
    [
    {
    name: 'HLS',
    url: 'a.m3u8',
    type: 'hls',
    },
    {
    name: 'FLV',
    url: 'demo.mp4',
    type: 'flv',
    },
    ],
    efaultQuality: 0,
    ic: 'demo.png',
    thumbnails: 'thumbnails.jpg',
    },
    }
    {% endmmedias %}

    不在表格内的参数请使用下面 JSON 类型的参数。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,由于允许使用 JSON5,此项配置几乎与 DPlayer 完全一致。

    详情请见上方示例。

    配置

    默认配置可写入 _config.yml

    mmedia:
    dplayer:
    js: [https://cdn.jsdelivr.net/npm/dplayer@1/dist/DPlayer.min.js](https://cdn.jsdelivr.net/npm/dplayer@1/dist/DPlayer.min.js)
    hls_js: [https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js](https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js)
    dash_js: [https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js](https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js)
    shaka_dash_js: [https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js](https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js)
    flv_js: [https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js](https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js)
    webtorrent_js: [https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js](https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js)
    default:
    contents:

    介绍

    可以插入 artplayer 标签。

    使用

    {% mmedia "artplayer" "url:[https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4"](https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4") %}
    {% mmedias "artplayer" "flv:"  %}
    {
    url: "[https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4"](https://dandoc.u2sb.com/video/%E5%AE%89%E8%A3%85/1-%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%89%E8%A3%85.mp4")
    }
    {% endmmedias %}

    参数

    此部分请熟读 ArtPlayer 文档](https://artplayer.org/document/#/options))

    • 使用 := 分割。

    详细参数表:

    参数默认解释
    url-url
    title-title
    poster-poster
    type-type
    autoplayfalsevideo autoplay
    loopfalsevideo loop
    volume0.7default volume
    style-style

    上面有一个比较特殊的参数 flv,这里单独解释一下,这个参数是用于引入其他 js 文件的,目前支持的有:hls dash shaka_dash flv webtorrent,上述参数可多个一起使用,如果后面带有 js 地址,将直接使用,否则将使用 _config.yml 配置或插件默认配置,如:

    {% mmedia "artplayer" "flv:" "url:a.flv" %}
    {% mmedias "artplayer" "flv:" "hls:[https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"](https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js") %}
    {
    ...
    }
    {% endmmedias %}

    不在表格内的参数请使用下面 JSON 类型的参数。

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,由于允许使用 JSON5,此项配置几乎与 ArtPlayer 完全一致。

    详情请见上方示例。

    配置

    默认配置可写入 _config.yml

    mmedia:
    artplayer:
    js: [https://cdn.jsdelivr.net/npm/artplayer@3/dist/artplayer.js](https://cdn.jsdelivr.net/npm/artplayer@3/dist/artplayer.js)
    hls_js: [https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js](https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js)
    dash_js: [https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js](https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js)
    shaka_dash_js: [https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js](https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js)
    flv_js: [https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js](https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js)
    webtorrent_js: [https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js](https://cdn.jsdelivr.net/npm/webtorrent/webtorrent.min.js)
    default:
    style: width:100%;height:650px;max-width:1200px;center
    contents:
    autoSize: true
    autoMini: true
    fullscreen: true
    fullscreenWeb: true

    介绍

    可以插入 bilibili 视频

    使用

    {% mmedia "bilibili" "bvid:BV1br4y1P7ND" %}
    {% mmedia "bilibili" "bvid:BV1br4y1P7ND" "danmaku:false" %}

    参数

    • 使用 := 分割。

    详细参数表:

    参数默认解释
    aid-aid
    bvid-bvid,与 aid 同时出现时以 bvid 为准
    page1page
    danmakutrue是否有弹幕 ture or false
    allowfullscreenallowfullscreen允许全屏, allowfullscreen 或 true 允许,其他选项不允许
    sandbox配置iframe sandbox
    width100%css 属性
    max_width850pxcss 属性
    marginautocss 属性

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,使用 JSON5 标准。

    配置

    默认配置可写入 _config.yml

    mmedia:
    bilibili:
    default:
    page: 1
    danmaku: true
    allowfullscreen: allowfullscreen
    sandbox: allow-top-navigation allow-same-origin allow-forms allow-scripts allow-popups
    width: 100%
    max_width: 850px
    margin: auto

    介绍

    可以插入 西瓜 视频

    使用

    {% mmedia "xigua" "xid=6925997698269053453" %}
    {% mmedia "xigua" "xid:6925997698269053453" "autoplay:true" %}

    参数

    • 使用 := 分割。

    详细参数表:

    参数默认解释
    xid-西瓜视频的 ID,就是那一串数字
    id-一般情况下不需要填写
    autoplayfalseautoplay
    startTime0开始时间,秒
    allowfullscreenallowfullscreen允许全屏, allowfullscreen 或 true 允许,其他选项不允许
    sandbox配置iframe sandbox
    width100%css 属性
    max_width850pxcss 属性
    marginautocss 属性

    JSON 参数

    mmedia 插件允许在 contents 部分使用 JSON 编写配置,使用 JSON5 标准。

    配置

    默认配置可写入 _config.yml

    mmedia:
    xigua:
    default:
    autoplay: false
    startTime: 0
    allowfullscreen: allowfullscreen
    sandbox: allow-top-navigation allow-same-origin allow-forms allow-scripts allow-popups
    width: 100%
    max_width: 850px
    margin: auto

    待开发…

    请前往 音乐界面 预览部分效果,分别用到了 Artplayer, Aplayer, Dplayer, Meting

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/introduction-of-plugin-tags-based-on-butterfly/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/playlist-conversion-of-major-music-platforms/index.html b/posts/playlist-conversion-of-major-music-platforms/index.html new file mode 100644 index 000000000..3c40ed2be --- /dev/null +++ b/posts/playlist-conversion-of-major-music-platforms/index.html @@ -0,0 +1,19 @@ +各大音乐平台歌单转换 | CC的部落格

    各大音乐平台歌单转换

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    各大音乐平台歌单转换你看到标题可能会问,我为什么要转换歌单,对于我这种支持正版但又不想掏钱的人来说,声破天的曲库的确满足了我,JOOX 泰国区丰富的泰语正版歌曲曲库也是不错的,因此一直在用,但我之前国内主流平台的歌单数据怎么办,难不成重新制作一份歌单?

    还有时差原因,有时候我们在其他海外流媒体音乐平台可以比国内抢先收听,因此在各大平台留下了一堆不同的歌单,甚至你的 YouTube 也有一堆音乐列表,但我想尽量只在一个平台听,如何快速导入呢?

    由于曲库原因(歌手名,歌曲名,版权也都有影响),会出现导入失败的情况,所以还是需要配合手动文本导入等方式

    国内各大平台转换

    这个虾米,网易,QQ 音乐等都有提供官方导入页面,以便大家在不同平台转换歌单,并且官方都配有教程,这里不再赘述

    使用 Soundiiz 完成国外 45 家平台转换

    Soundiiz 官网 | Soundiiz 官方教程

    这里也不再多说(就是我懒),首先注册账号,然后登陆,依然有烦人的谷歌人机验证,所以大陆用户请自行准备工具通过谷歌验证

    授权完成你想要转换的平台,然后开始自动同步歌单,点击歌单详情 -> 转换 按照步骤自行配置即可

    同时免费用户可以使用一个歌单的自动同步,操作步骤同理

    自动同步可选项

    显然这里因为歌手名字不匹配造成失败

    因为 Spotify 歌手名字是英语,而 JOOX 泰国站是泰语造成信息不匹配

    因此我们可以在设置里加入匹配规则(对应关系),对了如果你英语不是很好可以切换语言为中文中国

    这里基本完成两个平台的转换,其他平台同理

    算是比较大的平台,因此有合作,你的优秀歌单可以为你带来收益

    国内国外中转转换

    上面这个平台虽然很好用,但有一个致命缺点,对于大陆用户来说,那就是没有我们常用的平台,事实上一年多以前我就有反馈给官方客服 QQ 音乐,网易云的问题,但限于技术,暂时无法实现(几年过去了,还是没动静)

    网上各种转换网站也是很多,但就版权来说,Spotify 还是不错的,因此我们先把我们的歌单转移到 spotify,再转移到其他平台即可

    使用 https://spot.uselesses.com/#/ 即可

    当然配合 https://www.tunemymusic.com/zh-cn/ 食用也是很不错的,因为它支持通过上传 txt,m3u,xml,csv 等列表来获取导入其他平台,大家配合使用是真的不错,你可以使用其他第三方生成后导入,作为中转也是很好用

    当然还有其他许多平台,这里不再一一介绍,因为我考虑的是支持越多平台越好,希望将来把国内主流平台也支持吧,这样就省了很多事

    好了,这篇文章就水到这里了,下篇文章见

    依旧句末不想打句号

    当然不能忘了提前写一个后续更新

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/playlist-conversion-of-major-music-platforms/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/production-practice/index.html b/posts/production-practice/index.html new file mode 100644 index 000000000..3c47eaee9 --- /dev/null +++ b/posts/production-practice/index.html @@ -0,0 +1,19 @@ +生产实习 | CC的部落格

    生产实习

    生产实习 等待更新中 时间为整点定时发布

    待同步 取消加密 > 图片还未上传至图床 > 视频嵌入还未做好 YouTube 已 OK > 目录在左侧

    超声波及温度传感摇摆风扇
    所用元件:

    UNO R3 开发板 ×1

    大面包板 ×1

    舵机 ×1

    舵机支架 ×1

    电位器 ×1

    1k 电阻 ×1

    USB 数据线 ×1

    小风扇 ×1

    摇头风扇支架组件 ×1

    ULN2003AN 驱动芯片 ×1

    三色 LED ×1

    鳄鱼夹 ×2

    面包线 若干

    **开发环境:**Arduino IDE,Mind+
    预期要求:

    通过超声波测距和温度传感控制舵机是否旋转,当距离小于 30cm 或温度大于 30℃ 时在设定的角度之间来回旋转;通过电位器控制电机,小风扇旋转的快慢。

    大致设计思路:
    具体实现源代码:
    //引入库文件
    \#include <Servo.h>//舵机库,之间要有空格,否则编译时会报错。
    \#include <Wire.h> //是I2C通讯的,Arduino和I2C设备通讯使用的(SCLK DIN RCLK)
    //以下为函数声明
    void zhuan();
    void buzhuan();
    void chaoshengbo();
    void wendu();
    //以下为变量声明及初始声明
    Servo myservo;//定义舵机变量名
    unsigned char jiao;
    const int P=A0;//电位器输入引脚
    const int U=8;
    int sensorValue=0;//电位器电压值
    int outputValue=0;
    // 设定SR04连接的Arduino引脚
    const int TrigPin = 10;
    const int EchoPin = 11;
    unsigned long distance;
    int temp;//温度
    int tol;//校对码
    int j;
    unsigned int loopCnt;
    int chr[40] = {0};//创建数字数组,用来存放40个bit
    unsigned long time;
    \#define pin 2
    //以下为主函数部分
    void setup() //初始设定
    {
    myservo.attach(9);//定义舵机接口
    Serial.begin(9600);//设定波特率为9600
    pinMode(TrigPin, OUTPUT);// 要检测引脚上输入的脉冲宽度,需要先设置为输入状态
    pinMode(EchoPin, INPUT);
    Serial.println("Ultrasonic sensor:");
    buzhuan();
    chaoshengbo();
    wendu();
    }
    //以下为循环执行部分
    void loop()
    {
    chaoshengbo();
    wendu();
    delay(500);
    if ((distance<30) || (temp>30))
    {
    digitalWrite(4, LOW);//红灯灭,代表舵机未旋转
    digitalWrite(7, HIGH);//绿灯亮,代表舵机开始旋转
    zhuan();
    chaoshengbo();
    wendu();
    delay(500);
    }
    else if((distance>30) || (temp<30))
    {
    buzhuan();
    chaoshengbo();
    wendu();
    delay(500);
    }
    }
    //以下为函数定义部分
    void zhuan()//定义舵机转
    {
    myservo.write(jiao);
    sensorValue=analogRead(P);
    outputValue=map(sensorValue,0,1023,0,255);
    analogWrite(U,outputValue);
    for(jiao=30;jiao<150;jiao++)
    {
    myservo.write(jiao);//设置舵机旋转的角度
    delay(10);
    }
    for(jiao=150;jiao>30;jiao--)
    {
    myservo.write(jiao);//设置舵机旋转的角度
    delay(10);
    }
    }
    void buzhuan()//定义舵机不转
    {
    digitalWrite(TrigPin, LOW);
    delayMicroseconds(2);
    myservo.write(jiao);
    digitalWrite(4, HIGH);
    digitalWrite(7, LOW);
    sensorValue=analogRead(P);
    outputValue=map(sensorValue,0,1023,0,255);
    analogWrite(U,outputValue);
    myservo.write(jiao);
    }
    void chaoshengbo()//定义超声波测距
    {
    // 产生一个10us的高脉冲去触发TrigPin
    digitalWrite(TrigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(TrigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(TrigPin, LOW); // 检测脉冲宽度,并计算出距离
    //delayMicroseconds(2);
    distance = pulseIn(EchoPin, HIGH) / 58.00;
    Serial.print("距离:");
    Serial.print(distance);
    Serial.print("cm");
    Serial.println();
    }
    void wendu()//定义温度测量
    {
    bgn:
    delay(500);
    //设置2号接口模式为:输出
    //输出低电平20ms(>18ms)
    //输出高电平40μs
    pinMode(pin,OUTPUT);
    digitalWrite(pin,LOW);
    delay(20);
    digitalWrite(pin,HIGH);
    delayMicroseconds(40);
    digitalWrite(pin,LOW);
    //设置2号接口模式:输入
    pinMode(pin,INPUT);
    //高电平响应信号
    loopCnt=10000;
    while(digitalRead(pin) != HIGH)
    {
    if(loopCnt-- == 0)
    {
    //如果长时间不返回高电平,输出个提示,重头开始。
    Serial.println("HIGH");
    goto bgn;
    }
    }
    //低电平响应信号
    loopCnt=30000;
    while(digitalRead(pin) != LOW)
    {
    if(loopCnt-- == 0)
    {
    //如果长时间不返回低电平,输出个提示,重头开始。
    Serial.println("LOW");
    goto bgn;
    }
    }
    //开始读取bit1-40的数值
    for(int i=0;i<40;i++)
    {
    while(digitalRead(pin) == LOW)
    {}
    //当出现高电平时,记下时间“time”
    time = micros();
    while(digitalRead(pin) == HIGH)
    {}
    //当出现低电平,记下时间,再减去刚才储存的time
    //得出的值若大于50μs,则为‘1’,否则为‘0’
    //并储存到数组里去
    if (micros() - time >50)
    {
    chr[i]=1;
    }else{
    chr[i]=0;
    }
    }
    //温度,8位的bit,转换为数值
    temp=chr[16]*128+chr[17]*64+chr[18]*32+chr[19]*16+chr[20]*8+chr[21]*4+chr[22]*2+chr[23];
    //校对码,8位的bit,转换为数值
    tol=chr[32]*128+chr[33]*64+chr[34]*32+chr[35]*16+chr[36]*8+chr[37]*4+chr[38]*2+chr[39];
    //输出:温度、湿度、校对码
    Serial.print("温度:");
    Serial.print(temp);
    Serial.println("℃");
    }

    串口串口显示情况 1,此时温度为 28℃,距离为 275cm 左右,都不满足舵机旋转的条件,红色指示灯常亮。

    对应的实际运行情况如下图所示:

    串口串口显示情况 2,串口串口显示情况 1,此时温度为 28℃,距离为 5cm 左右,满足舵机旋转的条件,绿色指示灯常亮。

    对应的实际运行情况如下图所示

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/production-practice/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/research-on-image-denoising-technology-based-on-wavelet-transform/index.html b/posts/research-on-image-denoising-technology-based-on-wavelet-transform/index.html new file mode 100644 index 000000000..2d98f0c2a --- /dev/null +++ b/posts/research-on-image-denoising-technology-based-on-wavelet-transform/index.html @@ -0,0 +1,19 @@ +基于小波变换的图像去噪技术研究 | CC的部落格

    基于小波变换的图像去噪技术研究

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀 自动同步更新至CC 的部落格

    这篇文章占个坑,目前不会公开,因为成为了毕业论文

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/research-on-image-denoising-technology-based-on-wavelet-transform/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    avatar
    CC康纳百川
    CC的部落格,CC康纳百川的小窝,与你分享二三事
    多种订阅更新方式

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    最近更新
    \ No newline at end of file diff --git a/posts/resume-template/index.html b/posts/resume-template/index.html new file mode 100644 index 000000000..0c9763d22 --- /dev/null +++ b/posts/resume-template/index.html @@ -0,0 +1,19 @@ +简历模板 | CC的部落格

    简历模板

    简历模板 案例 A

    178XXXXXX46 | anli150151@foxmail.com

    求职意向:用户运营实习生

    教育经历

    成都工业学院                               国际商务本科                             2015.9 2019.7

    l GPA:3.24/5.0(专业排名 17/153)

    l 荣誉/奖项:校级乙等奖学金 2 次(6%)、丙等奖学金 1 次(10%)、挑战赛校级赛 2 等奖、解说员风采大赛 2 等奖。

    实习经历

    瑞禾英语                                外教老师助理                         2018.4-2018.6

    l 社群日常管理:协助外教负责 5个班级群管理,包括发放教学资料、组织班级学习,收集整理课程资料,记录 30 位学生单独的成长记录,形成文档保存;

    l **用户答疑解惑:**协调外教老师和 5 个班级在课堂中出现的各种问题并及时翻译。及时解答学生关于发音的疑问,最终有效地纠正了口语发音。

    l **调动课堂气氛:**为提高学生课程参与度,调动课堂气氛,策划小游戏等;

    l **课后辅导:**密切跟踪关注学生课后的复习情况和学习上遇到的困难,向学生介绍一些更有效的学习方法来提高英语水平;

    l 用户调研:利用 Word 协助制作并回收50 份家长调查问卷,调查 17 位家长的意见反馈,及时和老师们交流,对 6 次课程内容进行修改,优化教学内容和服务质量;

    中信银行郫都支行                      零售部客户经理助理                      2018.1-2018.2

    l **维护客户:**扩大客户群和完成贷款任务,维护和链家、中信地产和 Q 房网 3 家房产机构的业务关系。负责买卖及银行 3 方贷款资料等 10 份资料的收集和完善,进行贷款资料整理核实,协助初审等;

    l **后续跟踪:**处理客户还款申请及贷后管理,包括资料补办、跟踪贷款进度。维护客户关系,协助客户签署 3 份贷款合同文件。一个半月的实习里,完成 53 笔贷款业务。

    嘉祥九思教育                              晚辅老师                           2017.3-2017.6

    l **课堂纪律:**负责对 23 位同学日常签到和考勤,监督学生按时参加晚辅,是学生的签到率提到 14%。

    l **答疑解惑:**辅导小学生和初中生的语文、数学和英语作业,实时解决学生作业中遇到的困惑,及时与家长沟通并解决学生学业问题。所负责的学生,成绩提高到了 85 分,获得了家长的好评。

    校园经历

    经济与管理学院实践部                       骨干成员                        2015.09-2016.10

    l 组织 “三月学雷锋”颁奖仪式,负责活动策划,组织协调活动人员。活动有 486 人观看,仪式圆满成功。

    l 协助经济与管理学院“首届创新创业大赛”,负责人员组织和宣传工作。邀请了光谷创业咖啡的代表作为点评嘉宾,吸引了 103 同学参加。

    技能/证书及其他

    技能: Office 办公(熟练)

    证书/执照: acess 数据库(二级)、英语(六级 490 分、四级 450 分)

    语言: 英语口语(熟练)

    自我评价

    l 大四国际商务专业在读,分别在嘉祥九思、瑞和英语教育机构担任晚辅老师和助教,参与11 次英语课程内容的制作,在线解答各种学习困惑。负责30 人社群运营,包括调动课堂气氛、及时答疑、组织课堂纪律等;

    l 个人荣誉:3 次校级奖学金,全国大学生电子商务挑战赛校级赛 2 等奖等;

    l 职业规划:在教育领域深入发展,当前职业定位是用户运营岗位

    方方

    13722222457 | 22222222@163.com

    求职意向:人力实习生

    教育经历

    浙江科技学院                          英语专业本科                     2016.09 – 2020.07

    l GPA:3.67/5.0(综合排名 7/60)

    l 荣誉/奖项:校级三等奖学金 2 次、国家励志奖学金 2 次、优秀学生干部 1 次

    l 相关课程:高级口译、高级英语视听说、商务英语、英美文学

    活动经历

    浙江科技学院外国语学院学生会                 正主席                           2018.10-2019.01

    l **活动策划:**担任总策划人,负责院学生运动会开幕式的策划以及排演,召开 2 次学生会议后,在老师的指导下确定最终方案。

    l **活动执行:**负责现场彩排,组织 3 个班级共计 60 余人进行现场有序演练,耗费 2 天达成方阵表演效果,最终运动会开幕式圆满完成。

    浙江科技学院外国语学院英语 162 班             班长                             2017.09-2019.06

    l **协调分工:**带领班干部筹办班级迎新晚会,经过多次开会讨论,2 天之内形成具体方案,将任务细化分配到个人,督导晚会各环节进程,最终成功举办班级晚会,参与人数 27/31,获得班级同学的认可。

    l **组织彩排:**在学校开展校特优学风班评比比赛时,与老师班委一起策划现场评比表演,分配规划任务。赛前与比赛工作人员协商彩排时间并组织了 4 次彩排,在 17 个强劲班级中,取得了总分第二的好成绩。

    浙江科技学院外国语学院勤工助学处               负责人兼辅导员助理                  2018.09-2019.06

    l **沟通协调:**在从事勤工助学时,主要负责招聘岗位与人数的拟定,以及每隔两个月一次的薪酬统计。初始期间与院负责老师以及其他老师多次沟通协商,协调出最适合的用工人数及用工岗位,获得了负责老师的认可。

    多项志愿活动                               志愿者

    l **人员接待:**在世界医药健康信息学大会中担任酒店志愿者,负责与外宾沟通并迎接入住,大会信息咨询,会场班车引导,因服务细致热心,还收到了澳大利亚与会嘉宾的感谢与礼物。

    l **英语翻译:**在世界地理信息学大会中担任餐饮组志愿者,给参会国家部长及其家属提供餐饮服务,并担任翻译。

    此外还参加了浙江省口译大赛志愿者,浙江省-下奥地利商务论坛翻译人员。

    技能/证书及其他

    技能: Office 办公(熟练)

    **证书/执照:**英语(四级、六级),专业英语四级(笔试,口试)

    语言: 英语口语(熟练),日语(一般掌握)

    个人荣誉:“we talent”优秀学子;院学生会主席;优秀学生干部;全国大学生英语竞赛校二等奖;浙江省 LSCAT 笔译大赛二等奖;优秀志愿者

    [Name]

    [Phone Number] | [Email Address] | [Physical Address (make it short; just highlight where you are now)]

    (Reminder: 中英文简历各一页!改完后记得删除所有中括号)

    EDUCATION

    [University Name]                                                      [City], [State/Country]

    Bachelor of [Arts/Science]; Major in [Major]         [Start date (month/year)] – [End date (expected)]

    ·    GPA: [xx] / 4.0; [If you’re outside the US, list grades under your system here instead]

    ·    Honors/Awards: [xx]

    ·    Major Coursework: [Economics / Accounting / Finance classes, only the “hardcore” courses; highlight what content you learnt from the courses, rather than only list the official names of the courses]

    INTERNSHIP EXPERIENCE

    [Company Name 1]                                     [City], [State/Country]

    Explanation of the company (if it is not “big name”)

    [Position Title], [Group Name]                            [Start Date] – [End Date]

    ·    [Summary sentence stating what you did and the overall results of your work]

    ·    [Conducted research on the xx industry, covering market size, growth, trends and key success factors, which was used in the external study part of the strategic planning report for a xxx client]

    ·    [Collected such financial data as revenue, margin and cost breakdown of 10+ competitors of a client in XX industry through desktop research, analyzed the data through modeling, and the results were used for the competitor benchmarking and strategic recommendations report]

    ·    [Led a team of xxx members to organize a marketing campaign, which attracted xxx customers within xx days, and increased the sales of the month by xx% ]

    [Company Name 2]                                     [City], [State/Country]

    Explanation of the company (if it is not “big name”)

    [Position Title], [Group Name]                            [Start Date] – [End Date]

    ·    [Summary sentence stating what you did and the overall results of your work]

    ·    [Conducted research on the xx industry, covering market size, growth, trends and key success factors, which was used in the external study part of the strategic planning report for a xxx client]

    ·    [Collected such financial data as revenue, margin and cost breakdown of 10+ competitors of a client in XX industry through desktop research, analyzed the data through modeling, and the results were used for the competitor benchmarking and strategic recommendations report]

    ·    [Led a team of xxx members to organize a marketing campaign, which attracted xxx customers within xx days, and increased the sales of the month by xx% ]

    EXTRACURRICULAR ACTIVITIES

    [Student Club Name]                                   [City], [State/Country]

    [Position Title]                                        [Start Date] – [End Date]

    ·    [Summary sentence stating what you did and the overall results of your work]

    ·    [Led a team of xx people to organize xx activities to recruit xx new members, increasing the overall membership from xx to xx within xx months]

    ·    [Organized xx conference, which invited xx speakers and attracted xx audience]

    [Volunteer Work Name]                                 [City], [State/Country]

    [Position Title]                                        [Start Date] – [End Date]

    ·    [Summary sentence stating what you did and the overall results of your work]

    ·    [Organized xx activities …, which attracted xx participants / xx audience / helped xx people to xxx]

    ·    [Led a team of xx people to xxx]

    SKILLS & INTERESTS

    Languages: TOEFL [xx] / 120; IELTS [xx] / 9; CET-4/6 [xx] / 710; xx years’ overseas study and living experience

    Technical Skills: [List any programming languages – including MS Office/Excel]

    Certifications & Training: [Any extra courses or programs relevant to your target, e.g., CPA, CFA]

    Interests: [Keep this to 1-2 lines and be specific, e.g. Travelling (backpacked to 20 countries); Piano (Grade 10)]

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/resume-template/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/song-about-you-live-in-the-sky-2023/index.html b/posts/song-about-you-live-in-the-sky-2023/index.html new file mode 100644 index 000000000..dc393655e --- /dev/null +++ b/posts/song-about-you-live-in-the-sky-2023/index.html @@ -0,0 +1,19 @@ +2023《好好》线上演唱会 | CC的部落格

    2023《好好》线上演唱会

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    版权归属 台湾 相信音乐

    刘若英 X 苏慧伦 X 丁当 X 白安

    2023《好好》线上演唱会

    Song About You live in the sky 2023

    歌单一览

    已在视频中标出


    苏慧伦 part

    0:30 鸭子

    4:27 被动

    8:18 说话

    9:09 严重

    13:12 说话

    13:24 恋恋真言

    17:17 在我生命中的每一天 feat.丁当


    丁当 part

    21:58 开头

    22:39 夜猫

    26:13 花火

    30:18 说话

    31:07 猜不透

    35:12 说话

    37:25 女字旁

    41:56 我爱他


    白安 part

    46:54 不够特别的我不要

    51:41 刚好

    56:01 说话

    56:39 是什么让我遇见这样的你

    1:00:39 没有人写歌给你过吧

    1:05:39 让我逃离平庸的生活


    刘若英 part

    1:10:25 所有相爱的人啊

    1:14:28 成全

    1:18:57 说话

    1:20:55 固执

    1:25:47 缩影

    1:29:30 talking feat.白安

    1:31:20 妈妈 feat.白安

    1:35:51 后来

    1:40:52 快乐天堂 feat.苏慧伦、丁当、白安


    女加上子 每个女子生而为好

    该对自己好 该好好疼爱自己

    女子女子 就是好好

    好歌相伴 好上加好

    《好好》线上演唱会

    一场女子们的闺密音乐聚会

    宜尽兴 宜微醺 宜舒心 宜走心

    妳有多久没有好好跟自己说说话了?

    妳有多久没有好好聆听心底声音了?

    妳有多久没有好好跟好友聊聊天了?

    妳有多久没有好好欣赏美好事物了?

    女子,要好好去爱,更要好好爱自己。

    「3 月 8 日」是一年一度的「国际妇女节」 (International Women’s Day),提醒每个女子要爱自己,更能去爱别人、去爱这个世界。 在这个这个专属于女子的节日,刘若英 X 苏慧伦 X 丁当 X 白安,四个女子的美好相遇,要在 38 妇女节的周三夜,以音乐用心地打造出一场属于每个你的 “Lady’s Night”,你可以与你自己,也可以与好闺密们,一起好好享受、好好尽欢、好好聆听一首首动人的女子心声。

    如水 如石 如光 如树

    一场音乐与自然的飨宴

    将美好谱写 如歌而行

    当音乐遇见自然 当内心遇见自己

    美的时节 好的相遇

    女子女子 好好与你以歌相聚

    「女」加上「子」等于「好」,「女子」加上「女子」就是「好好」,好上加好! 「好好女声」刘若英、苏慧伦、丁当、白安,春暖花开时节献唱,,以歌相聚在《好好》线上演唱会,不仅渲染多首个人经典好歌,彼此间更有精彩的合唱新火花! 《好好》演唱会以「女野」概念,结合「水、石、光、树」为主题,女子在自然旷野里吟唱,呈现出如水之柔美、如石之坚强、如光之魔幻、如树之实在的演唱氛围。

    新的一年一切都在慢慢变好,刘若英、苏慧伦、丁当、白安,四美女子以美好歌声陪伴每个认真生活、认真爱的女子,一起告别因疫情闷久的坏坏情绪,迎接温暖美丽的好好心情

    视频版

    流媒体平台

    QQ 音乐 | 网易云音乐 | 酷狗音乐 | 酷我音乐 | 咪咕音乐 | 汽水音乐

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/special-test-article/index.html b/posts/special-test-article/index.html new file mode 100644 index 000000000..535bd8177 --- /dev/null +++ b/posts/special-test-article/index.html @@ -0,0 +1,19 @@ +语雀专用测试文章 | CC的部落格

    语雀专用测试文章

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀 自动同步更新至CC 的部落格 语雀专用测试文章当一切准备好后, 语雀主动推送更新文章才会触发 CI , Gitlab  单独触发单独构建 (一平台一仓库搞定所有, 赞, 要不是速度慢了点, 肯定值得推荐的) , 其他平台由 云函数   触发, 由 GitHub Actions  构建, 至此所有镜像站均可完成同步更新

    Hexo 标签测试


    一个无趣的人
    水调歌头
    苏轼

    丙辰中秋,欢饮达旦,大醉,作此篇,兼怀子由。明月几时有?把酒问青天。不知天上宫阙,今夕是何年?我欲乘风归去,又恐琼楼玉宇,高处不胜寒。起舞弄清影,何似在人间?转朱阁,低绮户,照无眠。不应有恨,何事长向别时圆?人有悲欢离合,月有阴晴圆缺,此事古难全。但愿人长久,千里共婵娟。


    关于写作格式 我想说首先就是恼人的 front-matter ,导入要注意格式(不然会被转换为二级标题),导出也要注意格式,真的很头疼,这个我想应该先给团队反馈所以原来的模板是不能用了, 本地和语雀要有两套模板, 但数据存在语雀还是很安全的

    ---
    title: 语雀专用测试文章
    tags: [语雀, 测试]
    categories: [语雀, 测试]
    cover: "https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_32.webp"
    top_img: false
    copyright_author_href: "https://www.ccknbc.cc/"
    keywords: "语雀,测试"
    description: 语雀测试专用文章
    id: 16
    date: 2020-12-15 20:00:00
    updated: 2020-12-16 10:30:00
    ---

    即使是这么写, 但要保证和不是 front-matter , 就像文章开头那样即可, 不然就会出问题啦如上所见, 其他内容无需注意, 均能正常渲染,

    1. front-matter  中的 链接  请使用引号(单引号双引号均可,中文也可,反正会格式化),不然同步过去会识别成 md  格式链接导致报错
    2. 或者当自动识别为链接后也可以鼠标点击链接后,点击取消链接选项变为黑色普通文字即可
    3. 关于上述,我们要记得导出格式为 markdown  而不是 hexo  以获得较好的兼容,以及线程设为一降低出错的可能性
    4. 外链  图片见下文
    5. 采用了 vercel 云函数 api

    外链引入图片测试

    https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_32.webp https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_32.webp !https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_32.webp 以上三种都是错误写法,格式可在语雀查看,下面是正确写法(也就是保证链接自动识别转换为 md  格式后在前面加上!变为 md 格式图片引用) 但这种写法在语雀无法查看的, 所以请使用 html  或 md (推荐) 语法, 以便在语雀也能正常查看不过导入的文章不用担心这些啦, 因为已经帮你转换好了导出也是正常的

    ![测试](https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_38.webp)

    <img
    src="https://cdn.jsdelivr.net/gh/ccknbc-backup/photos/blog/2020-10-12~18_03_38.webp"
    />

    <img
    data-role="image"
    src="https://cdn.nlark.com/yuque/0/2020/webp/8391407/1608118431216-b79b2e90-a0e6-4304-85a8-23475b588c77.webp?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_Q0PnmoTpg6jokL3moLw%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10%2Fresize%2Cw_1492"
    data-raw-src="https://cdn.nlark.com/yuque/0/2020/webp/8391407/1608118431216-b79b2e90-a0e6-4304-85a8-23475b588c77.webp?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_Q0PnmoTpg6jokL3moLw%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"
    class="image lake-drag-image"
    alt="oNGhAigG.webp"
    title="oNGhAigG.webp"
    style="visibility: visible; width: 691px; height: 389px;"
    />

    对于 动态图片  , 因为我开启了图片自动加水印, 所以无法正常显示, 但在编辑页面以及 HEXO 博客   是可以看到的,然后原来的图片也被转换成了

    看到上面的代码, 我就想问不过为什么不试试直接使用语雀上传图片呢, 这种方式也是个人比较推荐的, 而且可以很方便的设定图片参数, 添加水印等等, 访问还算快, 关键是稳定, 并且读者在语雀也能正常阅读, 所有可以试试把文章导入语雀


    语雀上传图片测试

    如果遇到上传到语雀的图片无法加载的问题, 可以参考这个处理方式 #41 我们可以修改主题模板来达到此效果


    使用体验

    这个需要过一段时间, 已经报名体验了新版工作台, 并且使用上了, 总的来说还是很方便的, 反馈问题的话也能很快得到回复, 团队是真的在用心做产品


    关于教程

    请前往教程: hexo× 语雀 实现云端富文本写作查看@小冰博客当然其中部分内容存在错误, 请读者自行斟酌


    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/special-test-article/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/ta-said-nothing/index.html b/posts/ta-said-nothing/index.html new file mode 100644 index 000000000..da2091249 --- /dev/null +++ b/posts/ta-said-nothing/index.html @@ -0,0 +1,19 @@ +Ta 什么都不说 | CC的部落格

    Ta 什么都不说

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    Ta 所认为的理所当然,原来根本就不存在

    本文首发在语雀 自动同步更新至CC 的部落格

    Ta,什么都不说

    • Ta 担心 Ta,但是 Ta 不说
    • Ta 怕打扰 Ta,所以 Ta 不说
    • Ta 想说但 Ta 还是选择了不说
    • Ta 似乎没有机会再说,Ta 还是不愿亲口说

    Ta 不说,也不让 Ta 说

    • Ta 有事总藏在心里,Ta 从不会与 Ta 说
    • Ta 说 Ta 还小,Ta 不能说
    • Ta 说 Ta 长大了,Ta 不再说

    后来,没人说了

    • Ta 总是偷抹眼泪,Ta 看到但 Ta 不说
    • Ta 知道 Ta 很累,但 Ta 不会说
    • Ta 身边有人,可 Ta 不知与谁说
    • Ta 习惯了一个人,Ta 不必再说
    • Ta 理解了 Ta,Ta 不知如何说

    现在说,还算晚吗?

    • Ta 说不出口,Ta 尝试去说
    • Ta 想向全世界的人大声地说
    • Ta 终于说了,原来 Ta 也想说
    • Ta 说 Ta 说 Ta ,但 Ta 想 Ta Ta Ta 说

    Ta 只与 Ta 说,Ta 只与 Ta 说,但 Ta 不知道 Ta 与 Ta 说

    Ta 与 Ta 说,Ta 不知道 Ta 说了什么,事实上 Ta 也不知道 Ta 说了什么

    Ta 终于还是自己和自己说,加油!

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/ta-said-nothing/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/the-real-addthis/index.html b/posts/the-real-addthis/index.html new file mode 100644 index 000000000..6cea46ad8 --- /dev/null +++ b/posts/the-real-addthis/index.html @@ -0,0 +1,19 @@ +你以为 AddThis 只是个分享工具吗? | CC的部落格

    你以为 AddThis 只是个分享工具吗?

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文首发在语雀,自动同步更新至CC 的部落格

    本文作废

    Notice of Termination of AddThis Services.

    What’s Changing?

    As part of a periodic product portfolio review, Oracle has made the business decision to terminate all AddThis services effective as of May 31, 2023.

    Key Dates

    Existing AddThis users can expect that after May 31, 2023:

    • the user must immediately cease its use of AddThis services, and promptly remove all AddThis related code and technology from its websites;
    • AddThis buttons may disappear from the user’s websites;
    • the AddThis dashboard associated with the user’s registration for AddThis, and all support for AddThis services, will no longer be available;
    • all features of AddThis configured to interoperate with user’s websites, any other Oracle services, or any third-party tools and plug-ins will no longer function.

    Oracle thanks you for your attention and understanding in this matter, and for the many years of allowing Oracle to provide this service to you.

    How Do I Uninstall the AddThis Button?

    If you’ve copied and pasted the code into your website, go back into the code and look for and , then delete these lines and any code between them. If you’ve used another method to install AddThis on your page, please contact us and we’ll be happy to help you.

    总结:终止服务,主题已移除

    Butterfly 如何使用

    打开 AddThis 官网,标语是 Turn your visitors into engaged customers. 听起来是个营销工具,但主题集成的时候选择了它,并且没有做特别说明,只是让我们找到 pub-id ,并没有说如何配置

    实际上要想和 AddToAny 或者 sharejs 一样使用文章内分享,我们得在控制台添加 Tools,就像下图所示 然后选择行内工具 后面样式部分就根据自己喜好和需求按钮多少,在哪些页面显示等来自行配置啦。比如我还同时选择了,自动展开分享按钮。而且他能很好的自适应,并且后台修改之后我们博客无需任何操作即可更新。

    其他工具

    但还有其他工具也很好用,比如你点进文章来之前,应该有弹窗提示你要阅读隐私政策,实际上这是链接推广工具的活用。再比如放在顶栏作为临时公告,并且都有很好的自适应人性化选择,你下滑就会收起来,上滑再弹出。同样如果你是文章页或者订阅页面,因为我配置了仅在这些页面显示,会弹出一个订阅文章更新弹窗,这里收集邮件工具派上了用场,并且与 Mailchimp 配合完成了这项工作,至于配置邮件订阅,可以查看之前的文章 为你的 Hexo 博客添加邮件订阅 不过为了邮件订阅,我同样整合到了 Tidio,详情见订阅页面。当然如果你也在乎其他平台的关注数量,可以使用关注按钮来实现推广效果,文章推荐和打赏这里还是建议使用主题自带的就好。此外它还配有统计分析工具(这里强烈推荐您阅读 隐私政策),以帮助你实现更好的内容转化。 所以结合起来正常情况下我开起了五个工具 当需要发布临时公告时,我会根据重要程度选择左下角或者顶栏 就免费来说,他做的很不错了,相比于专门做弹窗的 poptin 似乎更简单的与 mailchimp 集成,但毕竟术业有专攻,比弹窗肯定不如人家,不过白嫖来说已经够了,我也不用使用 snackbar 刷新 jsd 缓存来实现临时公告了。而我现在重新使用了 webpushr 来实现浏览器通知,不管是否订阅,我均可以发送公告,并可保留最近 3 条公告,然后这就涉及到了空间利用率和用户体验的问题,所以我就得考虑关闭一些小部件,比如邮件订阅弹窗(据说会影响搜索引擎权重),还有分享按钮。电脑上无所谓,手机上显得有点挤(不过可以选择根据设备或者宽度自适应是否显示),即使我放在右下角,分享按钮放在左下角。所以我在公告栏加入了邮件订阅表格,并添加链接导向订阅页,但毕竟也没人订阅,还是链接导向订阅页面吧。

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/the-real-addthis/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/the-webp-road-of-blog-pictures/index.html b/posts/the-webp-road-of-blog-pictures/index.html new file mode 100644 index 000000000..c4d4ccc48 --- /dev/null +++ b/posts/the-webp-road-of-blog-pictures/index.html @@ -0,0 +1,19 @@ +博客图片的 WebP 之路 | CC的部落格

    博客图片的 WebP 之路

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    博客图片的 WebP 之路在主流浏览器都支持的情况下,我趁着文章还少,把所有文章的图片全部转换为 WebP 格式,以寻求更快的加载速度和丝滑的体验

    这篇文章同样有很多不完善的地方,而且由于要写的比较详细的话,可能需要很多截图,而事实上这篇文章不会被太多人看到,所以有需要再进行更新

    WebP 转换

    个人呢,不喜欢为了这简单的事去下载一个专门的软件,所以必定是找了很久,在搜索引擎和论坛看评论,以及综合个人使用经验,推荐以下平台

    • 没广告,做该做的事
    • 参数可调整

    智图

    为什么推荐呢,因为对于临时的一张图片用起来还是不错的,而且图片品质参数可调,个人按需以及实际情况做单张图片转换或者优化压缩可使用这个平台

    WebP2jpg-online

    「无需上传的图片转换器-简单、隐私、快速」官网是这么介绍的啦,纯前端处理,所以速度快慢取决于你的设备性能,适合批量图片处理的情况,同时多参数可调整,处理完毕后会把所有文件打包压缩自动下载,当然支持的格式不仅仅是名字那两种

    对于 WebP 动态的处理,个人用多张 gif 试了一下,效果不是很理想,不推荐

    如果处理过程中,长时间进度卡着不动,没办法,刷新吧

    Gitee Pages(国内访问良好)

    GitHub Pages

    WebP - 图片格式的发展趋势 - 又拍云

    同时缺点吗就是不能快捷方便地选择图片质量(右下角有 api 调用方法,但是改参数真的不方便啊),而且我这边使用只能在控制台Console找报错图片地址,然后新标签页打开保存处理好的WebP动图,也是只支持单张图片处理,所以对于比较小的gif我还是推荐就用gif吧,除非你和我封面一样,几兆一张图必须得压缩,不然博客访问速度可想而知,同时浪费访客的流量

    GIF 到 WEBP 转换器

    这边测试呢,确实是支持转换的,但得到的图片比原图还大,所以不怎么推荐,但是还支持其他好多种格式转换,所以还是很香的

    图床

    网上的那些知名图床好是好,但就会偷偷删你文件,所以黑人问号,小众稳定的还是少不过备案了的话白嫖就很简单

    流浪图床

    5M 以下文件托管,支持了 WebP,api

    鸡霸图床

    10M 单文件,嗯

    鸡霸网盘

    30M 以下文件托管,支持了 WebP

    IMG.WANG

    图床,好吧大家用一个模板套出来的

    OneManager

    实际上就是利用微软的 OneDrive,如果你也配置了话,不如试试,实际访问速度还是取决于当地运营商,而他提供了游客图床的选项(自己上传了拿到的链接比较好控制,所以就没开),但我没开启(因为我用的云函数),可按照教程配置即可,支持 heroku 一键部署

    自动化

    方案

    我的博客图床仓库README这样写道

    • 本仓库文件使用PicGo上传
    • 其中图片使用gulp imagemin压缩
    • (之后考虑加入WebP转换 👍,gulp作者貌似不考虑适配,虽然imagemin测试成功了,但是还是等等再说)
    • GitHub Actions压缩完成
    • 每天早晚 8 点左右各执行一次压缩
    • 当然也可以手动点击压缩一次
    • 同时游客点击Star也会帮忙压缩一次(谢谢)
    • 图片上传完毕一会儿会由Imgbot压缩提交PR
    • 然后由Restyled进行代码格式重置(图片也不需要了其实)
    • 最后由MergifyGithub Actions自动合并PR(比速度 🚀)
    • (或由我打标签后由PRValet自动完成完成PR合并)

    全部换成WebP,不需要自动压缩了,虽然自动压缩是真的方便

    但还没完,如果继续使用GitHub做图床,jsDelivrCDN加速,我面临以下问题

    • 将来图片越来越多,仓库体积也会越来越大
    • 涉及到了 jsd 的滥用问题,万一哪天禁了,或者关系到我GitHub账户使用问题,后果很严重
    • 备份在哪,将来统一更换链接方便,有没有满足以下条件的图床
    1. 稳定,这是首要条件
    2. 免费,或者说够我这小型博客免费试用的量
    3. 支持批量上传下载,并且上传后文件名保持不变
    4. 支持API上传,以配合PicGo实现流畅的写作体验
    5. 相册功能要有,批量多种场景不同格式链接以适应不同需求
    6. 友好地支持 WebP 格式(包括动态)
    7. 访问速度还不错 …

    当然啦,这么显得我是不是过于贪心了,但真的没有一种比较好的解决方案,对我这种不是优秀博主的人也可以很好的使用免费资源为博客图片加速呢?

    A:我也在慢慢摸索中,所以这篇博文会持续更新下去

    准备

    1. PicGo 官网因为版本过多原因,这里不放加速下载链接,如果您访问过慢,不如试试加速脚本或者加速插件这里提供我个人搭建的加速站,您可以访问按照教程和说明下载
    2. 关于配置如果要写的话肯定要截图,这里放上别人的文章链接咯,大家自行比对 PicGo+GitHub 快速实现 markdown 图床
    3. 自动压缩
      1. 使用GitHub APP,也就是上面提到的
        • 图片上传完毕一会儿会由Imgbot压缩提交PR
      2. ImgBot optimizes your images and saves you time.
      • 按照要求选择免费计划,授权完毕后勾选需要压缩图片的仓库即可但这就涉及到了是手动合并 PR 还是自动合并 PR 的选择问题,如果你和我一样只要求压缩,实际上当一遍又一遍的压缩优化,推荐大家使用自动合并 PR 解决问题 - 然后由Restyled进行代码格式重置(图片也不需要了其实) - 最后由MergifyGithub Actions自动合并PR(比速度 🚀) - (或由我打标签后由PRValet自动完成完成PR合并)

    PNG JPG GIF

    如果是选择手动打标签完成合并,即使用PRValet,请前往安装,并按照要求进行配置

    How to use PR Valet

    1. Step 1: Install PR Valet.
    2. Step 2: Add the valet:merge label to your pull request.
    3. Step 3: Work on your other tasks while PR Valet takes care of merging your pull request.

    也就是在仓库启用后,去编辑一下 label 标签,添加一个名为valet:merge的标签,而机器人提交了 PR 后,我们打上这个标签,便会自动执行合并操作,之后 imgbot 将删除由imgbot创建的分支 imgbot,方便下次在进行自动压缩,提交 PR

    具体过程可通过下图查看(别问我为什么不重新截图)

    而我个人在建立博客的几个月中,当然希望啥都能自动化,啥都能免费白嫖,省心最好,因此选择了自动合并

    个人推荐使用mergify,因为它算是术业有专攻,老牌子信得过,功能强大,关键是配置也比较简单易懂

    教程就不写了(还是写了,往下看),跟着官方文档做就好(谷歌 Chrome 页面翻译?

    自动合并配置部分

    自动合并配置部分

    The Configuration File

    Mergify applies rules to your pull requests. To do that, you need to create a Mergify configuration in each repository where Mergify is used.

    The configuration file should be created in the root directory of the repository and named either .mergify.yml or .mergify/config.yml or .github/mergify.yml.

    As the file name implies, the configuration file format is based on YAML, a simplistic file format for data. The configuration file format is entirely documented in 🔖 Configuration File.

    上面官方文档给出了三种创建配置文件的目录,当然我是用第一种(越懒越好)直接根目录创建.mergify.yml文件,文件中的内容如下

    mergify 官方给出的例子其中包括了 imgbot,代码如下

    pull_request_rules:
    - name: automatic merge for ImgBot pull requests
    conditions:
    - author=imgbot[bot]
    - check-success=Travis CI - Pull Request
    actions:
    merge:
    method: merge

    你如果没使用 Travis CI,可以删掉那行,仅满足提交人为 imgbot 这个条件即可即可

    刚才的截图告诉我们,自动合并后,imgbot 将自动删除由它创建的imgbot分支,所以这里我们无需额外配置,我只是放在这里看看,假如 imgbot 不会自动删除分支呢

    由于此种方式不是通过 fork 创建的 pr,而是通过新建分支,所以必然需要删除无用的分支,别担心,这些都为你想到了,官方文档这么写道

    Some users create pull request from the same repository by using different branches — rather than creating a pull request from a fork. That’s fine, but it tends to leave a lot of useless branch behind when the pull request is merged.

    Mergify allows to delete those branches once the pull request has been merged:

    pull_request_rules:
    - name: delete head branch after merge
    conditions:
    - merged
    actions:
    delete_head_branch: {}

    实际上 Github 提供了自动删除分支选项,你可以去配置里打开它(如果以后在别的项目需要的话

    其他更多高级个性化配置可前往官方文档查看,万一以后需要自动合并指定人提交的 PR,还有上面的开启打标签合并选项等操作,再去配置相应的就行了(所以推荐记住这个平台)

    关于使用 Actions,如果已经了解并比较熟练的掌握的话推荐使用别人编写好的 actions,你只要 use 即可,配置建议查看自动合并 PR Actions 仓库,详情可以去看 README,但我建议自动合并 PR 的话两种方式选一种即可,不然万一报错邮件是我们不希望看到的而这个 actions 也能实现上面一样的效果,配置MERGE_FILTER_AUTHOR即可: When set, only pull requests raised by this author will be merged automatically.稍微复制粘贴,照着 README 配置即可,actions 教程网上也很多,请自行查看,或者直接查阅官方文档

    README 示例代码如下

    name: automerge
    on:
    pull_request:
    types:
    - labeled
    - unlabeled
    - synchronize
    - opened
    - edited
    - ready_for_review
    - reopened
    - unlocked
    pull_request_review:
    types:
    - submitted
    check_suite:
    types:
    - completed
    status: {}
    jobs:
    automerge:
    runs-on: ubuntu-latest
    steps:
    - name: automerge
    uses: "pascalgn/automerge-action@v0.12.0"
    env:
    GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

    关于这个GITHUB_TOKEN,在前文中配置 Picgo 提到过,用一样的即可,我们在项目仓库中添加 secrets 即可,当然按照官方文档配置的话,这个名字得叫GITHUB_TOKEN

    在 workflow 文档流里我们可以用${{ secrets.GITHUB_TOKEN }}做权限认证,是一个默认存在的变量,并不需要我们去添加 ACCESS_TOKEN,不过要是跨仓库还是要使用手动生成的 TOKEN,关于这点,可以查看官方文档相关内容

    要实现自动合并 imgbot 提交的 PR,我的 workflow 这么配置

    使用GitHub Actions,每天定时压缩

    这有个好处就是由于是本仓库文件,所以省去了Secrects配置,直接 push 就行,也比较省心,同时图片压缩质量是通过调整参数可控的,当然也可以再每次博客写完,图片上传完毕后手动压缩一次,达到可控效果,毕竟我们并不希望上传一张照片自动压缩一次,浪费资源哦

    自动压缩配置部分

    自动压缩配置部分

    我的 workflow 这么配置的

    name: Compress Image

    on:
    schedule:
    - cron: "0 0,12 * * *"
    workflow_dispatch:
    inputs:
    name:
    description: "自己手动压缩一次"
    required: false
    watch:
    types: [started] #游客帮忙手动压缩一次,不用判断

    jobs:
    deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
    uses: actions/checkout@v2
    with:
    ref: master

    - name: Setup Node
    uses: actions/setup-node@v2-beta
    with:
    node-version: "12.x"

    - name: Catch
    uses: actions/cache@v2
    id: cache-dependencies
    with:
    path: node_modules
    key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

    - name: Install Dependencies
    if: steps.cache-dependencies.outputs.cache-hit != 'true'
    run: |
    npm install

    - name: Compress
    run: |
    gulp

    - name: Deploy
    run: |
    git config --global user.name "github-actions[bot]"
    git config --global user.email "github-actions[bot]@users.noreply.github.com"
    git init
    git add -A
    git commit -m "$(date +"%Z %Y-%m-%d %A %H:%M:%S") Updated By Github Actions"
    git push

    # 当然啦也可以部署到别的分支,或者使用别人编写好的脚本来完成部署,同时也可以设置一下环境变量时区改为上海

    但你们需要替换一下这部分内容(因为没有package.json

        - name: Install Dependencies
    if: steps.cache-dependencies.outputs.cache-hit != 'true'
    run: |
    npm install gulp gulp-imagemin
    //安装依赖,插件,使用gulp帮忙完成压缩

    同时根目录需要有gulpfile.js,来完成配置

    var gulp = require("gulp");
    var imagemin = require("gulp-imagemin");

    // 壓縮 public/uploads 目錄內圖片
    gulp.task("minify-images", async () => {
    gulp
    .src(".public/uploads/**/*.*")
    .pipe(
    imagemin({
    optimizationLevel: 7, // 類型:Number 預設:3 取值範圍:0-7(優化等級)
    progressive: true, // 類型:Boolean 預設:false 無失真壓縮jpg圖片
    interlaced: true, // 類型:Boolean 預設:false 隔行掃描gif進行渲染
    multipass: true, // 類型:Boolean 預設:false 多次優化svg直到完全優化
    })
    )
    .pipe(gulp.dest("./blog")); //输出到blog文件夹
    });

    // 執行 gulp 命令時執行的任務
    gulp.task("default", gulp.parallel("minify-images"));

    这种老的配置方法主要是任务执行时间比较短,反正也是白嫖,执行个一个小时也不为过?

    那你可以替换为新版配置

    const gulp = require('gulp'); // 基础库
    const imagemin = require('gulp-imagemin'); // 图片压缩
    // pngquant = require('imagemin-pngquant'); // 深度压缩

    exports.default = () => (
    gulp.src('src/images/*')
    .pipe(imagemin())
    .pipe(gulp.dest('dist/images'))
    );

    // …
    .pipe(imagemin([
    imagemin.gifsicle({interlaced: true}),
    imagemin.mozjpeg({quality: 75, progressive: true}),
    imagemin.optipng({optimizationLevel: 5}),
    imagemin.svgo({
    plugins: [
    {removeViewBox: true}, // 移除svg的viewbox属性
    {cleanupIDs: false}
    ]
    })
    ]))
    // …

    // …
    .pipe(imagemin({
    interlaced: true,
    progressive: true,
    optimizationLevel: 5,
    svgoPlugins: [
    {
    removeViewBox: true
    }
    ]
    }))
    // …

    // …
    .pipe(imagemin([
    imagemin.svgo({
    plugins: [
    {
    removeViewBox: true
    }
    ]
    })
    ], {
    verbose: true
    }))
    // …

    请不要无脑复制,自行整合,开启关闭需要的,按照官方配置即可

    自动转换配置部分

    自动转换配置部分

    和自动压缩差不多,但我们说了,那是之前的解决方案,现在我们是要让博客使用 WebP,因此必须要向前看,自动转换为 WebP,同时 jsd 链接后缀也得自动改或者手动改,这我还在研究中

    • 其中图片使用gulp imagemin压缩
    • (之后考虑加入WebP转换 👍,gulp作者貌似不考虑适配,虽然imagemin测试成功了,但是还是等等再说)为什么这么说,已经配置了gulpfile.js,我不想再配置imagemin.js,少一个文件是一个文件

    还是用到了 gulp,所以 gulp还是要装

    配置差不多,用到的插件是

    npm install --save-dev gulp gulp-WebP

    gulpfile.js配置如下

    const gulp = require("gulp");
    const WebP = require("gulp-WebP");

    exports.default = () =>
    gulp.src("src/image.jpg").pipe(WebP()).pipe(gulp.dest("dist"));

    至于怎么编写 actions 工作流文件,你应该会了

    不过还是不能不考虑 imagemin 自己的插件,那是真好用

    具体可查看官方

    https://github.com/imagemin/imagemin

    https://github.com/imagemin/imagemin-gif2WebP

    如果是压缩 jpg,png,安装插件

    npm install imagemin imagemin-jpegtran imagemin-pngquant

    配置文件写在imagemin.js文件里面,说真的不错啊,命令是node imagemin.js

    const imagemin = require("imagemin");
    const imageminJpegtran = require("imagemin-jpegtran");
    const imageminPngquant = require("imagemin-pngquant");

    (async () => {
    const files = await imagemin(["images/*.{jpg,png}"], {
    destination: "build/images",
    plugins: [
    imageminJpegtran(),
    imageminPngquant({
    quality: [0.6, 0.8],
    }),
    ],
    });

    console.log(files);
    //=> [{data: <Buffer 89 50 4e …>, destinationPath: 'build/images/foo.jpg'}, …]
    })();

    但我们显然要转成 WebP,

    npm install imagemin imagemin-WebP

    具体配置如下,效果比较好

    const imageminWebP = require("imagemin-WebP");
    const convertPNGToWebP = () =>
    imagemin([PNGImages], output, {
    use: [
    imageminWebP({
    quality: 85,
    }),
    ],
    });
    const convertJPGToWebP = () =>
    imagemin([JPGImages], output, {
    use: [
    imageminWebP({
    quality: 75,
    }),
    ],
    });
    optimiseJPEGImages()
    .then(() => optimisePNGImages())
    .then(() => convertPNGToWebP())
    .then(() => convertJPGToWebP())
    .catch((error) => console.log(error));

    官方的话,给了一个区间

    const imagemin = require("imagemin");
    const imageminWebP = require("imagemin-WebP");

    (async () => {
    await imagemin(["images/*.{jpg,png,WebP}"], {
    destination: "images",
    plugins: [imageminWebP({ quality: 80 })],
    });

    console.log("Images optimized");
    })();

    下面是 gif 转 WebP,我还没本地测试,不知道是否是能转成和 gif 差不多的动图而不是静态 WebP

    npm install --save imagemin imagemin-gif2WebP
    const imagemin = require("imagemin");
    const imageminGif2WebP = require("imagemin-gif2WebP");

    (async () => {
    await imagemin(["images/*.gif"], {
    destination: "build/images",
    plugins: [imageminGif2WebP({ quality: 50 })],
    });

    console.log("Images optimized");
    })();

    或者也可以去官方仓库看看别的插件,配置用法,反正我觉得 imagemin 本身还是挺好用的(相比于 gulp)

    这里是一个早期的例子,现在有些已经过时

    npm i imagemin imagemin-giflossy imagemin-mozjpeg imagemin-pngquant imagemin-svgo imagemin-WebP
    // 安装依赖:npm i imagemin imagemin-giflossy imagemin-mozjpeg imagemin-pngquant imagemin-svgo imagemin-WebP

    const fs = require("fs");
    const path = require("path");
    const imagemin = require("imagemin");
    const imageminMozjpeg = require("imagemin-mozjpeg");
    const imageminPngquant = require("imagemin-pngquant");
    const imageminGiflossy = require("imagemin-giflossy");
    const imageminWebP = require("imagemin-WebP");
    const imageminSvgo = require("imagemin-svgo");

    //stream pipeline
    const util = require("util");
    const stream = require("stream");

    const imgMIMEList = {
    svg: "image/svg+xml",
    png: "image/png",
    jpg: "image/jpeg",
    jpeg: "image/jpeg",
    gif: "image/gif",
    bmp: "image/bmp",
    WebP: "image/WebP",
    ico: "image/x-icon",
    tif: "image/tiff",
    psd: "application/octet-stream",
    };

    //TODO:提示压缩率

    const fn_imagemin = async (ctx, next) => {
    const file = ctx.request.files.file; // 获取上传文件
    const reader = fs.createReadStream(file.path); // 创建可读流
    const ext = file.name.split(".").pop(); // 获取上传文件扩展名
    const dataMIME = "data:" + imgMIMEList[ext] + ";base64,"; //根据扩展名设定媒体类型

    const imgName = getRandomId() + "." + ext; //压缩图片文件名
    const imgSourcePath = `storage/upload/img`; //压缩源图片文件夹
    const imgResultPath = `storage/result/img`; //压缩目标文件夹

    const imgSourcePathFile = `${imgSourcePath}/${imgName}`; //压缩源图片路径
    const imgSourcePathFileCWD = path.resolve(process.cwd(), imgSourcePathFile); //压缩源图片绝对路径

    const imgSourcePathCWD = path.resolve(process.cwd(), imgSourcePath); //源文件夹绝对路径
    const imgResultPathCWD = path.resolve(process.cwd(), imgResultPath); //目标文件夹绝对路径

    const upStream = fs.createWriteStream(imgSourcePathFileCWD); // 创建可写流 存储源图片
    // reader.pipe(upStream);// 可读流通过管道写入可写流
    const pipeline = util.promisify(stream.pipeline);
    let resultData = null;
    await pipeline(reader, upStream);
    await imageCompress(imgSourcePathFile, imgResultPath, (imgBuffer) => {
    resultData = dataMIME + imgBuffer.toString("base64");
    }).catch((err) => {
    ctx.response.status = 201;
    });

    //删除图片
    setTimeout(() => {
    deleteFile(imgSourcePathCWD, imgName);
    deleteFile(imgResultPathCWD, imgName);
    }, 0);

    if (file) {
    ctx.response.body = resultData;
    } else {
    ctx.response.status = 204;
    }
    };

    /**
    * 压缩图片
    * @param {String} sourcePath
    * @param {String} resultPath
    * @param {Function} callback
    */
    async function imageCompress(sourcePath, resultPath, callback) {
    const files = await imagemin([sourcePath], {
    destination: resultPath,
    plugins: [
    imageminMozjpeg({
    quality: 70,
    }),
    imageminPngquant(),
    imageminGiflossy({
    lossy: 80,
    }),
    imageminWebP(),
    imageminSvgo(),
    ],
    });

    const imgBuffer = files[0].data;
    callback(imgBuffer);
    }

    /**
    * 获取随机id
    */
    function getRandomId() {
    return Math.random().toString(36).substr(2) + Date.now().toString(36);
    }

    /**
    * 删除某一个包下面的需要符合格式的文件。
    * @param {String} url 文件路径,绝对路径
    * @param {String} name 需要删除的文件名称
    * @return {Null}
    * @author huangh 20170123
    */
    function deleteFile(url, name) {
    let files = [];

    if (fs.existsSync(url)) {
    //判断给定的路径是否存在

    files = fs.readdirSync(url); //返回文件和子目录的数组

    files.forEach(function (file, index) {
    let curPath = path.join(url, file);

    if (fs.statSync(curPath).isDirectory()) {
    //同步读取文件夹文件,如果是文件夹,则函数回调
    deleteFile(curPath, name);
    } else {
    if (file.indexOf(name) > -1) {
    //是指定文件,则删除
    fs.unlinkSync(curPath);
    console.log("删除文件:" + curPath);
    }
    }
    });
    } else {
    console.log("给定的路径不存在!");
    }
    }

    module.exports = {
    "POST /upload/img": fn_imagemin,
    };

    我们原来还在顾忌 WebP 的支持问题,考虑自适应,加入判断,又拍云,https://WebP.sh/ 也提供这样的功能,但现在我的态度是,你看不到我博客的图片是你我无缘

    视频(题外话)

    鸡霸网盘 2 号

    视频文件小于 300M,免审核

    预览

    Teambition

    当阿里这个免费的办公协同工具诞生,我们在上传大文件视频进入播放页拿到 API 调用地址即可,不限速,临时使用(几天后地址会失效,或许有大神,蹲 API)

    OneManager

    实际上就是利用微软的OneDrive,如果你也配置了话,不如试试,实际访问速度还是取决于当地运营商

    预览

    关联阅读

    Gulp 中文文档

    Web 性能优化: 图片优化让网站大小减少 62%

    CDN 解决方案

    拿又拍云来说,图像处理,URL 作图 是个不错的解决方案

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/the-webp-road-of-blog-pictures/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/uptime-free-website-survival-monitoring/index.html b/posts/uptime-free-website-survival-monitoring/index.html new file mode 100644 index 000000000..74ed8e49f --- /dev/null +++ b/posts/uptime-free-website-survival-monitoring/index.html @@ -0,0 +1,19 @@ +Uptime 免费网站存活监控 | CC的部落格

    Uptime 免费网站存活监控

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    Uptime 免费网站存活监控

    前言

    对于静态托管网站来说,如果你放在不同的仓库,或者是托管服务商,那么有一个必要的网站存活监控是非常重要的,实时监控哪个仓库存活,哪个仓库无法访问,以便及时调整自己的线路。

    UptimeRobot 是一个免费提供网站存活监控的服务商,免费版本可以同时监控 50 个站点,最高频率可以达到 5 分钟一次,而且还可以自己生成公共页面以便访问,还可以绑定自定义域名。

    正文

    网站地址:https://uptimerobot.com/

    注册什么的就不用说了吧

    创建监视器

    注册完成之后登录会直接进入控制台

    创建新的监视器

    选择你要监视的方式,https 是通过访问的形式,ping 就是 ping 你的地址,port 就是监视端口

    这就创建好一个监视器啦

    生成公共页面

    我们要访问监视器总不能每次都登录吧,Uptime 贴心的准备了可以生成公共页面,还可以绑定自定义域名哦

    选择要显示的监视器,是全部显示还是只显示选中

    创建完成之后就可以使用你的自定义域名来访问啦,或者使用默认域名

    在这里进行访问

    这里是我的例子:大白萝卜の网站监控

    API

    如果你不喜欢他生成的页面,或者想要自己部署,那么你可以使用别人制作的主题,地址:

    两个一样,随便选一个

    fork 到自己仓库后,修改相关配置即可

    三种 APIkey 自己按照需要任选其一生成即可,在配置文件中进行修改,之后自己部署完毕就 OK 啦

    大佬的例子:Flexiston  的网站状态   卓越科技-  的网站状态

    文章作者: 大白萝卜
    文章链接: https://blog.dabailuobo.com/ba779920
    版权声明: 来源于大白萝卜(CC康纳百川获授权转载)
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/waline-comments-system-deployment-logs/index.html b/posts/waline-comments-system-deployment-logs/index.html new file mode 100644 index 000000000..f96c67ed3 --- /dev/null +++ b/posts/waline-comments-system-deployment-logs/index.html @@ -0,0 +1,19 @@ +Waline 评论系统部署日志 | CC的部落格

    Waline 评论系统部署日志

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    本文大部分内容已作废,请直接查看官方文档

    本文首发在语雀 自动同步更新至CC 的部落格 本文仅作为官方文档的补充,若有错误,还望指正 Waline 评论系统部署日志


    Waline - 一款从 Valine 衍生的带后端评论系统。可以将 Waline 等价成 With backend Valine.

    特性

    • 快速
    • 真·安全
    • Markdown 语法支持
    • 轻量易用
    • 免费部署
    • 多种部署部署方式和存储服务支持,每列选择一项多达 84 种(可以更多)部署方式任君选择
      Waline
      客户端脚本服务端部署数据存储
      @waline/clientVercelLeanCloud
      MiniValineCloudBaseCloudBase
      AprilCommentDockerMongoDB
      独立部署MySQL
      SQLite
      PostgreSQL
      GitHub

    对于想免费使用的用户, Vercel  + LeanCloud(国际版)  是不错的选择,不过Deta一个服务就能解决所有问题而且还快点,如果你主要面向对象为大陆用户,使用 CloudBase  部署也是个不错的选择,它在海外表现也没那么差,或者您仅使用 CloudBase  来做数据存储

    如果您使用 Vercel + LeanCloud ,并且使用 Vercel  发送评论通知,您不必担心 LeanCloud 流控问题,并且之前使用过 Valine 或者部署过 Valine-Admin  项目的可以直接拿来用;对于评论转移,官方提供了迁移助手供您使用,不用担心之前评论丢失的问题

    Todo

    微信通知

    QQ 通知

    Telegram 通知

    Akismet

    文章统计

    多语言同步

    自定义语言支持

    登录支持

    评论管理

    评论删除

    其它数据库支持

    基于 IP 的发布评论频率限制

    基于关键词的评论过滤限制

    IP 黑名单

    重复内容检测

    CloudBase 腾讯云开发部署支持

    社交登录

    AWS

    置顶评论

    评论赞踩

    其它…

    目前社交登录仅支持 GitHub , 未来会支持更多平台


    Vercel + LeanCloud 部署

    这部分请前往官方文档查看,不过需要注意的是如果你的 GitHub  账号主邮箱是 QQ  邮箱的话建议更改为其他邮箱(毕竟他们认为 QQ 邮箱是垃圾邮箱)再去注册 Vercel(或者你可以选择给客服发一封邮件让他们帮忙解锁你的账号),环境变量配置部分官方文档也写了,这里不再赘述如果您之前用过 Valine,那么关于 LeanCloud 部分你就不用做什么了,数据兼容,拿到那几个 key  即可

    配置项

    这个可直接参考官方文档按需进行配置即可,因为目前云开发因众所周知的原因不支持连接 Telegram  服务器,所以如果您要配置电报新评论通知,请使用 Vercel 进行配置,不过因为目前没有异步通知,加上反垃圾检测等功能,发布评论可能需要很长时间,这个我使用了 LeanCloud 来继续帮我发送通知(反正我也没什么评论,流控问题第二天补发评论也不是不可)

    对于邮件通知部分,目前的设定是,对于新评论,如果博主配置了 QQ/微信/Telegram 通知中任意一种或多种,则邮件通知将会取消,而对于回复(子评论),博主和被回复者(如果填了邮箱的话)均可收到邮件通知

    我目前使用的 Hexo Butterfly 主题已经从 3.5.0 beta3 版本起内置了 Waline 评论系统,如果您使用老版本主题请升级,或者根据您所用版本的 Valine 模板 pug 来照葫芦画瓢,根据官方配置进行对应修改,主题中 option 为可选配置,万一将来增加了某些配置,主题不必为此升级, bg 为主题配置项这里注意一下 serverURL 以及环境变量里的 SITE_URL 网址最后的斜杠因为作者没做兼容,所以不要带上 / ,导致跳转不到对应评论界面客户端脚本里可以通过 langMode.admin  这个配置自定义角标的文案,例如:

    function waline() {
    const Waline = require("@waline/client");
    new Waline({
    el: "#waline-comment",
    serverURL: "https://waline.vercel.app",
    path: window.location.pathname,
    visitor: true,
    lang: location.pathname.startsWith("/en/") ? "en" : "zh-CN",
    langMode: {
    admin: location.pathname.startsWith("/en/")
    ? "Administrator"
    : "可爱的管理员",
    },
    });
    }

    对于同主题在主题配置里找到 waline  配置项相关内容

    # waline - A simple comment system with backend support fork from Valine
    # https://waline.js.org/
    waline:
    serverURL: https://waline.ccknbc.ml # Waline server address url
    avatar: monsterid # gravatar style https://zh-tw.gravatar.com/site/implement/images/#default-image
    bg: # waline background
    emojiCDN: https://cdn.jsdelivr.net/gh/GamerNoTitle/ValineCDN@master/
    visitor: false
    option:
    pageSize: 10
    requiredFields: mail
    # anonymous: false
    placeholder:
    avatarCDN: https://sdn.geekzu.org/avatar/
    #https://valinecdn.bili33.top/
    langMode:
    admin: 博主兼管理员
    nick: 昵称(选填)
    mail: 邮箱(必填)
    link: 网址(选填)
    sofa: 这里冷冷清清的,快来留下脚印吧!
    # 如果你查看了源码,会发现还有这个可以配置 copyRight: false,但不建议大家设为 false 啦,保留也没什么的(没错,我不要脸)

    还有就是可能有人会觉得默认邮件通知模板太单调,想和 Valine-Admin 一样切换模板,其实有这个配置的,只是目前的方法是写在环境变量中,而环境变量限制长度(大小),或者说是不适合这种方式配置,如果要改的话可以先查看issues/106相关内容,或者等以后优化再说;当然如果你的评论不是很多,并且之前配置过 Valine-Admin,那么你仍然可以使用 LeanCloud 来做异步发送通知,关闭默认的通知配置,或者使用 js 推送关于邮件模板大家可查看官方文档相关章节,或者使用附录提供的邮件通知模板,也提交了 PR

    评论 Hooks,可以根据官方的例子自己做一些配置,相比于其他,违禁词,屏蔽 IP 等配置可以说是人性化了,但万一配置不好一些正常评论可能也会被判定为垃圾内容,所以我推荐使用人工审核功能,不过这边不得不说另一个评论系统 Twikoo,支持查看自己审核中的评论,评论置顶,点赞等,不过我想 Waline 将来也能实现,毕竟 Flag 立那了

    图片上传 uploadImage 部分配置 理论上是可以适配任何图床,配置例子可查看 issues/123,当然内置了一个默认图床,开箱即用

    表情配置和之前 Valine 是一样的,同主题还可使用 walien.json  的配置方式,具体可查看主题文档

    CloudBase 云开发部署

    一键部署

    一键脚本部署可以查看官方文档,我删了之后就没成功过 截至文档最新更新日期,这个已被修复(不过 tcb-starter 那个链接还没改所以还是失败),不过我只能说作者非常不细心,毕竟能一天发十几个版本,详见 commit,他还是把链接协议头多打了一个 h ,所以请点击这里一键部署嗯,后来修复了,期待接下来的开发


    警告内容来自 Twikoo 官方文档 建议您直接查看 手动部署部分!!!

    一键部署虽然方便,但是仅支持按量计费环境——也就是说,一键部署的环境,当免费资源用尽后,将会产生费用。且按量计费环境无法切换为包年包月环境。免费额度数据库读操作数只有 500 次 / 天,无法支撑 Twikoo 的运行需求。Twikoo 建议您手动部署以节约成本。

    对于新用户或者说没有创建过按量计费环境的用户会显示如下内容,记得勾选开启免费资源

    为了日后升级的方便,不管您是否使用了 Vercel 部署,您都可以 fork 我的仓库 ,稍加配置即可完成自动部署更新

    手动部署

    首先前往腾讯云的活动区域,注册/登陆后往下滑,找到新用户专享云开发标准型(基础版 1)资源套餐,0 元购买一个免费包年包月环境


    没错,这个环境不错吧 按照提示购买后稍等几分钟,在这个界面可查看您所购买的环境 有能力的其实可以看一下 Vercel 自动升级和 TCB自动升级部分,间接实现一键部署,自动更新点击云函数,新建云函数,函数内存选择 128M,名称随意,例如 Waline,其他默认,单击进入下一步 下图中的函数代码部分填入以下代码

    /**
    * Tencent is pleased to support the open source community by making CloudBaseFramework - 云原生一体化部署工具 available.
    *
    * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
    *
    * Please refer to license text included with this package for license details.
    */
    module.exports.main = async (event, context) => {
    context.callbackWaitsForEmptyEventLoop = false;
    const entry = (() => {
    const result = require("./app.js");
    // const app = require('express')();
    // result = app.use(result);
    return result;
    })();
    const serverless = require("serverless-http");
    let app = entry;

    // support for async load app
    if (entry && entry.tcbGetApp && typeof entry.tcbGetApp === "function") {
    app = await entry.tcbGetApp();
    }

    return serverless(app, {
    binary: [
    "application/javascript",
    "application/json",
    "application/octet-stream",
    "application/xml",
    "font/eot",
    "font/opentype",
    "font/otf",
    "image/*",
    "video/*",
    "audio/*",
    "text/comma-separated-values",
    "text/css",
    "text/javascript",
    "text/plain",
    "text/text",
    "text/xml",
    ],
    })(event, context);
    };

    点击对应的云函数,进入在线编辑页面,按照模板仓库里的文件,新建对应的文件,并复制粘贴对应的内容即可 注意点击保存并安装依赖,可能会没有反应一会儿,然后等待转圈圈部署完毕即可 当然还没有结束,我们需要点击 环境 --> HTTP 访问服务 (点击直达),如果你想绑定自定义域名可以照图中绑定,记得先申请一下证书,如果你想要 HTTPS(这个可能花的时间有点长) 点击新建,新建触发路径,点击保存即可,注意路径最后没有 / ,等待构建完成后你就可通过对应的链接访问 demo 页面了,这个链接就是上面提到的 serverURL ,例如我的 https://tcb.ccknbc.cc/waline 然后我们需要设置 WEB 安全域名,把你的域名放入白名单即可(本地测试的话端口也要对应上哦)

    如何升级

    Vercel

    手动升级

    找到 Vercel 帮你在创建的仓库,叫 waline  啦,编辑 package.json  中依赖版本号即可完成升级,版本号以 npm   为准,因为 GitHub 由于考虑到电报机器人自动推送消息过于频繁影响到群友,会延迟推送

    自动升级

    其实原理还是一样的,因为 Vercel 会监控仓库文件的变化来帮我们自动部署,那么我们要做的就是自动更改版本号,这里你可以用 Github Actions  实现,定时每隔半小时自动更新并 push,但这样似乎有点浪费资源,所以不怎么推荐,而我们这个仓库通常都是公开的(私有也没关系)首先你需要安装一个应用Renovate,选择免费版计划即可,他会帮我们监控所用依赖的版本更新变化,并为提交一个 PR ,我们要做的只是合并 PR 而已,但手动合并之前也讲过,多少有点不方便,自动合并我们知道有打标签自动合并,GitHub Actions 工具人自动合并,这些大家搜以下关键词就好,但这个应用它本身实际上支持自动合并,查看官方文档发现在 renovate.json  中配置即可,示例代码如下,其中代理人是为了通知更新的作用,与 PR 同理,但也可删除此段配置,同样的 PR 也可关闭通知静默自动更新。

    {
    "extends": ["config:base"],
    "assignees": ["CCKNBC"],
    "separateMinorPatch": true,
    "packageRules": [
    {
    "updateTypes": ["minor", "patch"],
    "automerge": true,
    "automergeType": "branch"
    }
    ]
    }

    我目前还是用的默认的提交 PR 自动合并的方式,如果你是公开仓库,还可以使用Mergify,安装完成后他能它免费帮我们自动合并公开仓库的 PR,我们设定一个条件,比如 PR 提交作者为 renovate,就自动帮我们点击合并,并删除多余分支,当然这些都需要配置,这里具体会在另一篇文档中讲到

    以上两个应用你可以选择安装到全部仓库,或者只安装到选择的仓库

    如果你想懒的话可以先删除你现有的名为 Waine 的仓库,再 fork 我的仓库,然后去你的 Vercel 解绑之前的仓库,再绑定你 fork 的仓库,最后点一下重新部署即可但是如果你没用 tcb 就把 .github/workflows/Update Waline TCB.yml   里的文件删掉,因为涉及到自动部署更新云开发,还有环境变量问题,如果没设定会导致报错

    CloudBase


    一键部署

    就是点击我的应用找到 Waline 点击部署即可

    手动部署

    手动升级

    就是去仓库复制粘贴修改过的文件的事情了,如果没有文件改动就点击 保存并安装依赖  即可(知道在哪了吧)

    自动升级

    原理在上面讲了,结合 Vercel 自动升级部分查看,这部分其实可以作为上面的手动部署,或者自动部署?你可以 fork 我的仓库 进行更改,和上面提到的原理差不多,只是用到了 Actions(如果你之前没接触过这些,建议使用 Vercel 部署或者上面的一键部署,也比较方便),在合并 PR 后帮我们自动升级部署到云开发,解释一下几个密钥,您需要在 仓库的 settings/secrets/actions 中配置,组织的话可以把常用到的密钥添加为组织密钥,比如 ID KEY 等

    变量名变量解释
    SECRETIDAPI 访问密钥 ID,可点击这里新建/查看
    SECRETKEYAPI 访问密钥 KEY,可点击这里新建/查看
    TCBFUNNAME(没什么好加密的,就叫 waline 算了)你想要新建/已有函数的名称,比如 Waline
    TCBENVID环境 ID,可点击这里这里查看,地址栏后也会显示,反正就是很多地方都在上面点一下就能看到

    附录

    邮件通知模板

    mailSubject: '{{parent.nick}},您在 {{site.name}} 上发表的评论,收到了来自 {{self.nick}} 的回复',
    mailSubjectAdmin: '{{site.name}} 上收到了来自 {{self.nick}} 的留言',
    mailTemplate: '<head><base target="_blank"/><style id="scrollbar"type="text/css">::-webkit-scrollbar{width:0!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}#letter img{max-width:300px}</style><style id="from-wrapstyle"type="text/css">#form-wrap{overflow:hidden;height:447px;position:relative;top:0px;transition:all 1s ease-in-out.3s;z-index:0}</style><style id="from-wraphoverstyle"type="text/css">#form-wrap:hover{height:1300px;top:-200px}</style></head><body><div style="width: 530px;margin: 20px auto 0;height: 1000px;"><div id="form-wrap"><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/before.png"alt="before"style="position: absolute;bottom: 126px;left: 0px;background-repeat: no-repeat;width: 530px;height: 317px;z-index:-100"><div style="position: relative;overflow: visible;height: 1500px;width: 500px;margin: 0px auto;transition: all 1s ease-in-out .3s;padding-top:200px;"<form><div style="background: white;width: 95%;max-width: 800px;margin: auto auto;border-radius: 5px;border: 1px solid;overflow: hidden;-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);"><img style="width:100%;overflow: hidden;"src="https://area.sinaapp.com/bingImg"/><div style="padding: 5px 20px;"><br><div><h3 style="text-decoration: none; color: #8fbc8f;">{{parent.nick}},见信安:</h3></div><br><div id="letter"style="overflow:auto;height:300px;width:100%;display:block;word-break: break-all;word-wrap: break-word;"><p style="display: inline-block;">您在<a style="text-decoration: none;color: #8fbc8f"target="_blank"href="{{site.postUrl}} display: inline-block;">{{site.name}}</a>上发表的评论:</p><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{parent.comment | safe}}</div><p>收到了来自{{self.nick}}的回复:</p><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{self.comment | safe}}</div></div><br><div style="text-align: center;margin-top: 40px;"><img src="https://ae01.alicdn.com/kf/U0968ee80fd5c4f05a02bdda9709b041eE.png"alt="hr"style="width:100%; margin:5px auto 5px auto; display: block;"/><a style="text-transform: uppercase;text-decoration: none;font-size: 14px;border: 2px solid #ace0f9;color: #FFFFFF;padding: 10px;display: inline-block;margin: 10px auto 0;background-color: #8fbc8f;"target="_blank"href="{{site.postUrl}}">{{site.name}}|请您签收~</a></div><p style="font-size: 12px;text-align: center;color: #999;">自动书记人偶竭诚为您服务!<br>©2020 - 2021 <a style="text-decoration:none; color:#8fbc8f"href="{{site.url}}">{{site.name}}</a></p></div></div></form></div><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/after.png"alt="after"style=" position: absolute;bottom: -2px;left: 0;background-repeat: no-repeat;width: 530px;height: 259px;z-index:100"></div></div></body>',
    mailTemplateAdmin: '<head><base target="_blank"/><style id="scrollbar"type="text/css">::-webkit-scrollbar{width:0!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}#letter img{max-width:300px}</style><style id="from-wrapstyle"type="text/css">#form-wrap{overflow:hidden;height:447px;position:relative;top:0px;transition:all 1s ease-in-out.3s;z-index:0}</style><style id="from-wraphoverstyle"type="text/css">#form-wrap:hover{height:1300px;top:-200px}</style></head><body><div style="width: 530px;margin: 20px auto 0;height: 1000px;"><div id="form-wrap"><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/before.png"alt="before"style="position: absolute;bottom: 126px;left: 0px;background-repeat: no-repeat;width: 530px;height: 317px;z-index:-100"><div style="position: relative;overflow: visible;height: 1500px;width: 500px;margin: 0px auto;transition: all 1s ease-in-out .3s;padding-top:200px;"><form><div style="background: white;width: 95%;max-width: 800px;margin: auto auto;border-radius: 5px;border: 1px solid;overflow: hidden;-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);"><img style="width:100%;overflow: hidden;"src="https://area.sinaapp.com/bingImg"/><div style="padding: 5px 20px;"><br><div><h3 style="text-decoration: none; color: #8fbc8f;">来自{{self.nick}}的留言:</h3></div><br><br><div id="letter"style="overflow:auto;height:300px;width:100%;display:block;word-break: break-all;word-wrap: break-word;"><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{self.comment | safe}}</div></div><div style="text-align: center;margin-top: 40px;"><img src="https://ae01.alicdn.com/kf/U0968ee80fd5c4f05a02bdda9709b041eE.png"alt="hr"style="width:100%; margin:5px auto 5px auto; display: block;"/><a style="text-transform: uppercase;text-decoration: none;font-size: 14px;border: 2px solid #ace0f9;color: #FFFFFF;padding: 10px;display: inline-block;margin: 10px auto 0;background-color: #8fbc8f;"target="_blank"href="{{site.postUrl}}">{{site.name}}|请您过目~</a></div><p style="font-size: 12px;text-align: center;color: #999;">©2020 - 2021 <a style="text-decoration:none; color:#8fbc8f"href="{{site.url}}">{{site.name}}</a></p></div></div></form></div><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/after.png"alt="after"style=" position: absolute;bottom: -2px;left: 0;background-repeat: no-repeat;width: 530px;height: 259px;z-index:100"></div></div></body>'

    下载

    邮件通知模板下载(包含 Waline/Valine/Twikoo),您可以下载后根据官方文档提及的变量自行修改index.js相关内容,以上代码仅作参考,对于本文未涉及到的其他内容,请自行查看官方文档,如有错误,欢迎指正,谢谢!

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/waline-comments-system-deployment-logs/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/why-did-i-choose-tidio-as-the-chat-system/index.html b/posts/why-did-i-choose-tidio-as-the-chat-system/index.html new file mode 100644 index 000000000..4bd0e0515 --- /dev/null +++ b/posts/why-did-i-choose-tidio-as-the-chat-system/index.html @@ -0,0 +1,19 @@ +我为什么选择了 Tidio 做聊天系统 | CC的部落格

    我为什么选择了 Tidio 做聊天系统

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    我为什么选择了 Tidio 做聊天系统使用了很多聊天系统后,在这里做一个心得总结,虽然至今无人问津,但还是要坚持下去,有一天会有有缘人上门的

    以以下几个为例:Chatra, Tidio, Daovoice, Gitter, Crisp可以说是各有长处,但我的想法是在免费的基础上获得更好的体验,可能这就是我最后选择了Tidio的原因`

    Chatra

    适合中小企业级别,发展客户,推广商品之类的,界面只有英语,无法更改语言,对于不懂英语的人来说不是很友好,但都是些简单单词,就还好,免费版的话说实话功能是足够的,可以记录访客从哪个网页发起对话,但一旦访客发起对话,就自动记录了访客 IP,并且需要高级版才能查看,虽然一般没什么用处,但对于骚扰信息还是 OK 的

    Crisp

    同样也是定位于服务企业,所有当网站实际上只有你一个人,它还是会发送我们有什么可以帮您的,标配预调查填写信息,自适应语言(这点真的很赞,虽然自定义程度太差,毕竟给你翻译就挺好的),实时全球访客地图,机器人等都是很实用的功能,可控制访客是否可以发送附件,总体上自定义程度 ok,颜值也还在线,免费版确实也够用的

    Gitter

    创建聊天室或者社区,更适合程序员使用,不过 issue 他不香吗

    Daovoice

    国内服务商,微信通知绝对好评,相对比较简约,不过以上这些都带有邮件通知,所以不用担心漏掉消息啦,邮件通知还是比较好看的,然后可以向曾经的访客批量发送通知(好功能但是不推荐,应该把主动权交给用户,还不如 webpush),它的定位也是企业级别

    Tidio

    下面进入正题

    1. 虽然他的官网是只支持英文,但是小部件语言你可以添加几个并自行翻译(比如根据台湾地区语言习惯在地化一些繁体中文显得更亲切),这样一来自定义程度其实是很好的,然后你就可以获得和你现在看到的界面这样的效果
    2. 小部件渐变色真是深得我心,颜值瞬间提升,你还可以根据不同设备设定或排除显示界面,不同设备有不同的位置大小,Sidebar 也是极好的,但本站集成了按钮所以不能按照原来的显示,您可以自行尝试
    3. 电子邮件通知 footer 自定义,也是一种推广
    4. 插件方便营销,不过配合谷歌事件分析还是很赞的
    5. 机器人引导,免费的够用了,很大的操作空间
    6. 自定义快速回复,这个其他的也有配备
    7. 主要是给了用户更多选择,告知用户我可能会记录你的IP等隐私信息,算是一种信任培养官方小部件概览离线状态在线状态

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/why-did-i-choose-tidio-as-the-chat-system/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file diff --git a/posts/why-github-actions-is-so-popular/index.html b/posts/why-github-actions-is-so-popular/index.html new file mode 100644 index 000000000..7b101b10f --- /dev/null +++ b/posts/why-github-actions-is-so-popular/index.html @@ -0,0 +1,19 @@ +Github Actions 为什么这么香 | CC的部落格

    Github Actions 为什么这么香

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    Github Actions 为什么这么香

    本文存在大量纰漏待修正

    Github Actions为什么这么香,我为什么专门建了一个组织ccknbc-actions来跑 actions 并储存博客源码,或者其他只是单纯来跑 actions 的项目,一开始就单纯只是想分类,forked 一堆,主账号自己的项目却混在其中,最新的反而是天天运行 actions 的(排在前面)

    而对大多数博主来说,都是把自己的源码(包含源文章)仓库私有起来,而一个普通账号每个月私有仓库运行时间为 2000 分钟,确实,是完全够用的,对于我们这种月更博主来说一个月 100 分钟而已(好吧我就是懒);不过作为白嫖党我还是公开了仓库(这样就不限制运行时间了),但如果你选择了定时执行某些项目,注意间隔最小为5分钟,而触发方式也是多种多样的,但最让人欣喜的是手动触发方式终于完成了技术革命,不再监控 star 动作了,而是只有项目所有者可执行,这样就不会再运行记录里出现一堆无关记录影响查看(虽然之前判断仓库所有者也是 OK,但是强迫症不接受两秒运行跳过无关记录)

    而且由于分配的临时机性能还不错,速度还是很可观的,并且不受长城防火墙的限制,可以很方便的做一些其他事情,这里就不细说,回到标题,它为什么这么香呢?

    可能在工作流文件书写上没其他第三方简单,用过Travis CI或者Gitlab CI的都应该有体会,但自家的经过这么久的发展,用起来还是比较舒服的,而且用户编写的 actions 可以直接拿来用发布到市场,这样有些功能的实现就不用再自己想半天去实现,几行代码就搞定,用 HEXO 写博客的都知道 Gitee 托管静态网页要更新的话就得手动点一下更新才行,而 actions 就可以帮我们去点一下以实现同步全自动更新,多平台部署

    Github 本身自带的模板是 OK 的,但毕竟很多新手完全不懂,但其实上手一段时间就明白了每一步在做什么为什么要这样写,官方文档的例子虽然很简单但确实是包含了常用的一些步骤,再加上很多人分享,直接拿来用就行,毕竟搜索引擎不能摆在那不用,爬几篇文章学习一下就会了,这里我以部署 HEXO 博客为例来说一下

    首先我们得明白,要让 Github 能在你 git push 上去后能自动部署博客,你得知道博客的源文件是必须要的,但备份哪些呢,下图只是以本站做一个示例,框中的是必须要有的(如果你不打算修改主题源码其实也不用备份,但毕竟可以节约时间,第一次备份前记得在主题文件夹删掉.git隐藏文件夹,不然推上去是空的会导致运行失败),其他根据个人需求,,配一个证书或者 README 等,但你还在疑惑;我没有.github 文件夹啊,没错这个就是我们自己新建的文件夹,在博客根目录依次建立.github/workflows/*.yml文件

    就像下图这样,工作流文件.yml 你可以随便命名啦,然后我们在工作流文件中添加如下内容

    name: Update Blog Butterfly Site

    on:
    push:
    branches:
    - master
    workflow_dispatch:
    inputs:
    name:
    description: "手动触发"
    required: false

    jobs:
    deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
    uses: actions/checkout@v2
    with:
    ref: master

    - name: Setup Node
    uses: actions/setup-node@v2-beta
    with:
    node-version: "12.x"

    - name: Install HEXO CI
    run: |
    npm install hexo-cli -g

    - name: Catch
    uses: actions/cache@v2.1.1
    id: cache-dependencies
    with:
    path: node_modules
    key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

    - name: Install Dependencies
    if: steps.cache-dependencies.outputs.cache-hit != 'true'
    run: |
    npm install

    - name: Generate
    run: |
    hexo clean
    git clone https://github.com/CCKNBC/butterfly.git public
    hexo generate
    gulp

    - name: Deploy
    run: |
    cd ./public
    git config --global user.name "你的用户名"
    git config --global user.email "你的邮箱"
    git add -A
    git commit -m "Updated By Github Actions"
    git push --force --quiet "https://ccknbc:${{ secrets.GH_TOKEN }}@github.com/ccknbc/butterfly.git" master:master
    git push --force --quiet "https://ccknbc:${{ secrets.GT_TOKEN }}@gitee.com/ccknbc/butterfly.git" master:master
    git push --force --quiet "https://${{ secrets.CD_USER }}:${{ secrets.CD_TOKEN }}@e.coding.net/ccknbc/blog/butterfly.git" master:master

    - name: Build Gitee Pages
    uses: yanglbme/gitee-pages-action@master
    with:
    gitee-username: ccknbc
    gitee-password: ${{ secrets.GITEE_PASSWORD }}
    gitee-repo: ccknbc/butterfly

    在 workflow 文档流里我们可以用 ${{ secrets.GITHUB_TOKEN }} 做权限认证,是一个默认存在的变量,并不需要我们去添加 ACCESS_TOKEN,跨仓库的话还是要自己手动生成一个,关于这点,可以查看官方文档相关内容

    你可能有所疑惑但又看得懂一些命令,别急,请接着往下看

    GitHub Actions 指南

    GitHub Actions使你可以直接在你的GitHub库中创建自定义的工作流,工作流指的就是自动化的流程,比如构建、测试、打包、发布、部署等等,也就是说你可以直接进行 CI(持续集成)和 CD(持续部署)

    基本概念

    1. workflow: 一个 workflow 工作流就是一个完整的过程,每个workflow 包含一组 jobs任务
    2. job : jobs任务包含一个或多个job ,每个 job包含一系列的 steps 步骤
    3. step : 每个 step 步骤可以执行指令或者使用一个 action 动作
    4. action : 每个 action 动作就是一个通用的基本单元

    说明:

    1. 最外层的 name 指定了 workflow的名称
    2. on 声明了一旦发生了 push 操作就会触发这个 workflow
    3. jobs定义了任务集,其中可以有一个或多个job 任务,示例中只有一个
    4. runs-on 声明了运行的环境
    5. steps定义需要执行哪些步骤
    6. 每个 step可以定义自己的 nameid,通过 uses 可以声明使用一个具体的 action,通过run 声明需要执行哪些指令。
    7. 可以使用上下文参数on 声明了何时触发 workflow  ,它可以是:
      1. 一个或多个GitHub 事件,比如 push 了一个 commit 、创建了一个issue ,产生了一次pull request 等等,示例:
    on:[push,pull_request]
    1. 预定的时间,示例(每天零点零分触发,不过因为时差关系,是北京时间上午 8 点):
    on:
    schedule: -cron:'0 0 * * *'
    1. 某个外部事件。所谓外部事件触发,简而言之就是你可以通过REST APIGitHub 发送请求去触发,具体请查阅官方文档: repository-dispatch-event

    配置多个事件,示例:

    ```yaml
    on:

    # Trigger the workflow on push or pull request,

    # but only for the master branch

    push:

    branches:

    - master

    pull_request:

    branches:

    - master

    # Also trigger on page_build, as well as release created events

    page_build:

    release:

    types: # This configuration does not affect the page_build event above

    - created

    详细文档请参考: 触发事件


    ## jobs

    `jobs`可以包含一个或多个 `job` ,如:

    ```yaml
    jobs:

    my_first_job:

    name: My first job

    my_second_job:

    name: My second job

    如果多个job 之间存在依赖关系,那么你可能需要使用 needs :

    jobs:

    job1:

    job2:

    needs: job1

    job3:

    needs: [job1, job2]

    这里的needs声明了job2 必须等待 job1 成功完成,job3必须等待 job1job2依次成功完成

    每个任务默认超时时间最长为 360分钟,你可以通过 timeout-minutes 进行配置:

    jobs:
    job1:
    timeout-minutes:

    runs-on & strategy

    runs-on 指定了任务的 runner 即执行环境,runner 分两种:GitHub-hosted runnerself-hosted runner

    所谓的 self-hosted runner 就是用你自己的机器,但是需要 GitHub 能进行访问并给与其所需的机器权限,这个不在本文描述范围内,有兴趣可参考 self-hosted runner

    GitHub-hosted runner 其实就是 GitHub 提供的虚拟环境,目前有以下四种:

    1. windows-latest : Windows Server 2019
    2. ubuntu-latestubuntu-18.04
    3. ubuntu-16.04 : Ubuntu 16.04
    4. macos-latest : macOS Catalina 10.15

    比较常见的:

    runs-on:ubuntu-latest

    runs-on 多环境

    有时候我们常常需要对多个操作系统、多个平台、多个编程语言版本进行测试,为此我们可以配置一个构建矩阵

    例如:

    runs-on: ${{ matrix.os }}

    strategy:

    matrix:

    os: [ubuntu-16.04, ubuntu-18.04]

    node: [6, 8, 10]

    示例中配置了两种os操作系统和三种 node版本即总共六种情况的构建矩阵, `${{matrix.os}}` 是一个上下文参数

    strategy 策略,包括:

    1. matrix: 构建矩阵
    2. fail-fast : 默认为true ,即一旦某个矩阵任务失败则立即取消所有还在进行中的任务
    3. max-paraller : 可同时执行的最大并发数,默认情况下 GitHub 会动态调整

    示例:

    runs-on: ${{ matrix.os }}

    strategy:

    matrix:

    os: [macos-latest, windows-latest, ubuntu-18.04]

    node: [4, 6, 8, 10]

    include:

    # includes a new variable of npm with a value of 2 for the matrix leg matching the os and version

    - os: windows-latest

    node: 4

    npm: 2

    include声明了 oswindows-latest 时,增加一个 nodenpm分别使用特定的版本的矩阵环境

    include 相反的就是exclude

    runs-on: ${{ matrix.os }}

    strategy:

    matrix:

    os: [macos-latest, windows-latest, ubuntu-18.04]

    node: [4, 6, 8, 10]

    exclude:

    # excludes node 4 on macOS

    - os: macos-latest

    node: 4

    exclude 用来删除特定的配置项,比如这里当osmacos-latest,将 node为 4 的版本从构建矩阵中移除

    steps

    steps 的通用格式类似于:

    steps:

    - name: <step_name>

    uses: <action>

    with:

    <parameter_name>: <parameter_value>

    id: <step_id>

    continue-on-error: true


    - name: <step_name>

    timeout-minutes:

    run: <commands>

    每个 step 步骤可以有:

    1. id : 每个步骤的唯一标识符
    2. name : 步骤的名称
    3. uses : 使用哪个action
    4. run: 执行哪些指令
    5. with: 指定某个action 可能需要输入的参数
    6. continue-on-error : 设置为 true 允许此步骤失败job 仍然通过
    7. timeout-minutes : step 的超时时间

    action

    action 动作通常是可以通用的,这意味着你可以直接使用别人定义好的action

    checkout action

    checkout action 是一个标准动作,当以下情况时必须且需要率先使用:

    1. workflow 需要项目库的代码副本,比如构建、测试、或持续集成这些操作
    2. workflow 中至少有一个 action是在同一个项目库下定义的

    使用示例:

    - users:action/checkout@v1

    如果你只想浅克隆你的库,或者只复制最新的版本,你可以在 with中使用fetch-depth声明,例如:

    - user:action/checkout@v1
    with:
    fetch-depth:1

    引用 action

    1. 官方action标准库: github.com/actions
    2. 社区库:marketplace

    引用公有库中的 action

    引用 action 的格式是{owner}/{repo}@{ref}{owner}/{repo}/{path}@{ref},例如上例的中actions/checkout@v1,你还可以使用标准库中的其它 action,如设置 node 版本:

    jobs:

    my_first_job:

    name: My Job Name

    steps:
    - uses: actions/setup-node@v1

    with:

    node-version: 10.x

    引用同一个库中的 action

    引用格式:{owner}/{repo}@{ref}./path/to/dir

    例如项目文件结构为:

    -- hello-world (repository)

    |__ .github

    └── workflows

    └── my-first-workflow.yml

    └── actions

    |__ hello-world-action

    └── action.yml

    当你想要在workflow 中引用自己的action 时可以:

    jobs:

    build:

    runs-on: ubuntu-latest

    steps:
    # This step checks out a copy of your repository.

    - uses: actions/checkout@v1

    # This step references the directory that contains the action.

    - uses: ./.github/actions/hello-world-action

    引用 Docker Hub 上的 container

    如果某个 action 定义在了一个docker container image 中且推送到了Docker Hub 上,你也可以引入它,格式是docker://{image}:{tag} ,示例:

    jobs:

    my_first_job:

    steps:
    - name: My first step

    uses: docker://alpine:3.8

    更多信息参考:Docker-image.yml workflowCreating a Docker container ``action

    构建 actions

    请参考:building-actions

    env

    环境变量可以配置在以下地方:

    1. env
    2. jobs.<job_id>.env
    3. jobs.<job_id>.steps.env

    示例:

    env:

    NODE_ENV: dev


    jobs:

    job1:

    env:

    NODE_ENV: test


    steps:

    - name:

    env:

    NODE_ENV: prod

    如果重复,优先使用最近的那个

    if & context

    你可以在 jobstep中使用if条件语句,只有满足条件时才执行具体的jobstep :

    1. jobs.<job_id>.if
    2. jobs.<job_id>.steps.if

    任务状态检查函数:

    1. success() : 当上一步执行成功时返回 true
    2. always() : 总是返回 true
    3. cancelled() : 当 workflow被取消时返回 true
    4. failure() : 当上一步执行失败时返回 true

    例如:

    steps:

    - name: step1

    if: always()


    - name: step2

    if: success()


    - name: step3

    if: failure()

    意思就是 step1总是执行,step2 需要上一步执行成功才执行,step3 只有当上一步执行失败才执行

    ${{<expression>}}

    上下文和表达式: ${{}}

    有时候我们需要与第三方平台进行交互,这时候通常需要配置一个token,但是显然这个 token 不可能明文使用,这种个情况下我们要做的就是:

    1. 在具体 repositorySettingsSecrets 中添加一个密钥,如 SOMEONE_TOKEN

    注:关于如何获取 github 或者其他平台的密钥及授权不是本文重点,大家可以自行百度

    1. 然后在workflow中就可以通过 ${{secrets.SOMEONE_TOKEN}}token安全地传递给环境变量
    steps:
    - name: My first action

    env:

    SOMEONE_TOKEN: ${{ secrets.SOMEONE_TOKEN }}

    这里的secrets 就是一个上下文,除此之外还有很多,比如:

    1. github.event_name : 触发workflow的事件名称
    2. job.status : 当前job 的状态,如 success, failure, or cancelled
    3. steps.<step id>.outputs : 某个 action 的输出
    4. runner.os : runner的操作系统如 Linux, Windows, or macOS

    这里只列举了少数几个

    另外在if 中使用时不需要 ${{}} 符号,比如:

    steps:
    - name: My first step

    if: github.event_name == 'pull_request' && github.event.action == 'unassigned'

    run: echo This event is a pull request that had an assignee removed.

    上下文和表达式详细信息请参考:contexts-and-expression

    看到这里你应该对示例文件有了一定的理解,并且想自己去实验一下了,那就去 actions 页面找到官方示例去体验一下吧

    但对于为什么要备份package.json我想大家还是心存疑惑,那我们看看具体内容吧

    {
    "name": "hexo-site",
    "version": "0.0.0",
    "private": true,
    "scripts": {
    "build": "hexo generate",
    "clean": "hexo clean",
    "deploy": "hexo deploy",
    "server": "hexo server"
    },
    "hexo": {
    "version": "5.2.0"
    },
    "dependencies": {
    "cheerio": "^1.0.0-rc.3",
    "gulp-htmlmin": "^5.0.1",
    "hexo": "^5.2.0",
    "hexo-baidupush": "^1.0.2",
    "hexo-charts": "^1.0.3",
    "hexo-cli": "^4.2.0",
    "hexo-deployer-git": "^2.1.0",
    "hexo-generator-archive": "^1.0.0",
    "hexo-generator-baidu-sitemap": "^0.1.9",
    "hexo-generator-category": "^1.0.0",
    "hexo-generator-feed": "^3.0.0",
    "hexo-generator-index": "^2.0.0",
    "hexo-generator-search": "^2.4.1",
    "hexo-generator-sitemap": "^2.1.0",
    "hexo-generator-tag": "^1.0.0",
    "hexo-render-pug": "^2.1.4",
    "hexo-renderer-ejs": "^1.0.0",
    "hexo-renderer-marked": "^3.3.0",
    "hexo-renderer-pug": "^1.0.0",
    "hexo-renderer-stylus": "^2.0.1",
    "hexo-server": "^2.0.0",
    "hexo-tag-aplayer": "^3.0.4",
    "hexo-wordcount": "^6.0.1",
    "pump": "^3.0.0",
    "terser": "^4.8.0"
    },
    "devDependencies": {
    "gulp": "4.0.2",
    "gulp-cli": "2.3.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-htmlclean": "^2.7.22",
    "gulp-uglify": "^3.0.2"
    }
    }

    我们看到里面包含了 npm 脚本和一些依赖(包含 dev 版本的),有了这个文件我们只需执行 npm i(install)即可自动安装所以所需依赖插件,而不用一个一个去敲一堆命令啦,理解了这个简单的例子,大家在部署其他项目时也许能更得心应手吧

    今天的分享就到这里结束了,本文还有很多纰漏还请读者指出,后续将更正,下篇文章见

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/why-github-actions-is-so-popular/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/posts/yuque-to-hexo/index.html b/posts/yuque-to-hexo/index.html new file mode 100644 index 000000000..96876a03a --- /dev/null +++ b/posts/yuque-to-hexo/index.html @@ -0,0 +1,19 @@ +语雀文章同步至Hexo笔记 | CC的部落格

    语雀文章同步至Hexo笔记

    AI-摘要
    切换
    CC GPT
    AI初始化中...
    介绍自己
    生成本文简介
    推荐相关文章
    前往主页
    前往tianli博客

    查看本文语雀版本【首发】,自动同步更新至CC 的部落格

    建议直接查看结尾,新项目!但本文中的思路仍可借鉴,缓存缩小到了 1/12!

    因为 CC 已经使用语雀有一段时间了,但是因为使用的是 GitHub Actions 的原因,一直没有做什么更新,但是目前json已经 10M 了,是时候给缓存找一个地方存档以便后续增量更新了其实最开始的时候是直接推送到仓库的,后来有想过推送到npm的想法,但因为更新不怎么频繁也就一直耽搁了,但是因为不在使用条款范围内,有一定的风险,所以还是放弃了。在国庆前我就有想法传到One Drive这样的网盘,但是还是不是很方便,最好有现成的脚本可以使用。于是我想到了Artifacts构建产物这个东西,我只要先预先生成一次产物,然后下次就能把之前的产物下载下来使用,

    关于工作流程构件

    构件允许您在作业完成后保留数据,并与同一工作流程中的另一个作业共享该数据。 构件是指在工作流程运行过程中产生的文件或文件集。 例如,在工作流程运行结束后,您可以使用构件保存您的构建和测试输出。 All actions and workflows called within a run have write access to that run’s artifacts.

    默认情况下,GitHub 会将构建日志和项目存储 90 天(对于源码公开的我,公共仓库是完全够用的,只要保证 90 天更新一次博客即可),此保留期可以自定义。 有关详细信息,请参阅“使用限制、计费和管理”。 每当有人向拉取请求推送新提交时,拉取请求的保留期都会重新开始计算。

    以下是您可以上传的一些常见构件:

    • 日志文件和核心转储文件
    • 测试结果、失败和屏幕截图
    • 二进制或压缩文件
    • 压力测试性能输出和代码覆盖结果

    存储构件时使用存储空间 GitHub。 GitHub Actions usage is free for standard GitHub-hosted runners in public repositories, and for self-hosted runners. For private repositories, each GitHub account receives a certain amount of free minutes and storage for use with GitHub-hosted runners, depending on the product used with the account. Any usage beyond the included amounts is controlled by spending limits. 有关详细信息,请参阅“GitHub Actions 的计费”。

    构件会在工作流程运行过程中上传,您可以在 UI 中查看构件的名称和大小。 当构件使用 GitHub UI 下载时, 作为构件一部分单独上传的所有文件都会压缩到一个 zip 文件中。 这意味着计费是根据上传的构件大小而不是 zip 文件的大小计算的。

    GitHub 提供两项可用于上传和下载构建构件的操作。 有关详细信息,请参阅 actions/upload-artifactdownload-artifact 操作。

    要在作业之间共享数据:

    • 上传文件:为上传的文件指定一个名称,并在作业结束前上传数据。
    • 下载文件:只能下载在同一工作流运行期间上传的工件。 下载文件时,您可以通过名称引用该文件。

    作业步骤共享运行器机器的相同环境,但在其各自的进程中运行。 要在作业的步骤之间传递数据,您可以使用输入和输出。 有关输入和输出的详细信息,请参阅“GitHub Actions 的元数据语法”。

    比较构件和依赖项缓存

    构件与缓存类似,因为它们能够在 GitHub 上存储文件,但每项功能都提供不同的用例,不能互换使用。

    • 当想要重复使用在作业或工作流运行之间不频繁更改的文件时(例如从程序包管理系统构建依赖项),请使用缓存。
    • 如果要保存作业生成的文件,以在工作流运行结束后查看(例如生成的二进制文件或生成日志),请使用项目。

    有关依赖项缓存的详细信息,请参阅“缓存依赖项以加快工作流”。

    上传构建和测试构件

    您可以创建持续集成 (CI) 工作流程来构建和测试您的代码。 有关使用 GitHub Actions 执行 CI 的详细信息,请参阅“关于持续集成”。

    构建和测试代码的输出通常会生成可用于调试测试失败的文件和可部署的生产代码。 您可以配置一个工作流程来构建和测试推送到仓库中的代码,并报告成功或失败状态。 您可以上传构建和测试输出,以用于部署、调试失败的测试或崩溃以及查看测试套件范围。

    可以使用 upload-artifact 操作上传工件。 上传构件时,您可以指定单个文件或目录,或多个文件或目录。 您还可以排除某些文件或目录,以及使用通配符模式。 建议为工件命名,如果没有命名,则会使用 artifact 作为默认名称。 有关语法的详细信息,请参阅 actions/upload-artifact 操作。

    示例

    例如,您的仓库或 Web 应用程序可能包含必须转换为 CSS 和 JavaScript 的 SASS 和 TypeScript 文件。 假设生成配置输出 dist 目录中已编译的文件,如果所有测试均已成功完成,则可将 dist 目录中的文件部署到 Web 应用服务器。

    |-- hello-world (repository)
    | └── dist
    | └── tests
    | └── src
    | └── sass/app.scss
    | └── app.ts
    | └── output
    | └── test
    |

    此示例演示了如何创建 Node.js 项目的工作流,该项目在 src 目录中生成代码,在 tests 目录中运行测试。 可以假定运行 npm test 会生成一个名为 code-coverage.html、存储在 output/test/ 目录中的代码覆盖率报告。

    工作流上传 dist 目录中的生产工件,但不包括任何 Markdown 文件。 它还将 code-coverage.html 报表作为另一个工件上传。

    name: Node CI

    on: [push]

    jobs:
    build_and_test:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
    uses: actions/checkout@v3
    - name: npm install, build, and test
    run: |
    npm install
    npm run build --if-present
    npm test
    - name: Archive production artifacts
    uses: actions/upload-artifact@v3
    with:
    name: dist-without-markdown
    path: |
    dist
    !dist/**/*.md
    - name: Archive code coverage results
    uses: actions/upload-artifact@v3
    with:
    name: code-coverage-report
    path: output/test/code-coverage.html

    配置自定义构件保留期

    您可以为工作流程创建的单个构件自定义保留期。 使用工作流创建新工件时,可以同时使用 retention-daysupload-artifact 操作。 此示例演示如何为名为 my-artifact 的工件设置 5 天的自定义保留期:

    retention-days 值不能超过存储库、组织或企业设置的保留限制。

    - name: "Upload Artifact"
    uses: actions/upload-artifact@v3
    with:
    name: my-artifact
    path: my_file.txt
    retention-days: 5

    下载或删除构件

    在工作流运行期间,可以使用 actions/download-artifact操作下载以前在同一工作流运行中上传的工件。

    工作流程运行完成后,您可以在 GitHub 上或使用 REST API 下载或删除构件。 有关详细信息,请参阅“下载工作流工件”、“删除工作流工件”和“工件 REST API”。

    在工作流程运行期间下载构件

    actions/download-artifact操作可用于在工作流运行期间下载以前上传的工件。

    注意:只能下载在同一工作流运行期间上传的工作流中的工件。

    指定构件的名称以下载单个构件。 如果在未指定名称的情况下上传了工件,则默认名称为 artifact

    - name: Download a single artifact
    uses: actions/download-artifact@v3
    with:
    name: my-artifact

    您还可以不指定名称而下载工作流程运行中的所有构件。 如果您在处理大量构件,此功能非常有用。

    - name: Download all workflow run artifacts
    uses: actions/download-artifact@v3

    如果下载所有工作流运行的工件,则会为每个工件使用其名称创建一个目录。

    有关语法的详细信息,请参阅 actions/download-artifact 操作。

    在工作流中的作业间传递数据

    可以使用 upload-artifactdownload-artifact 操作在工作流中的作业间共享数据。 此示例工作流程说明如何在相同工作流程中的任务之间传递数据。 有关详细信息,请参阅 actions/upload-artifactdownload-artifact 操作。

    依赖于以前作业构件的作业必须等待依赖项成功完成。 此工作流使用 needs 密钥来确保 job_1job_2job_3 按顺序运行。 例如,job_2 需要 job_1,方法是使用 needs: job_1 语法。

    作业 1 执行以下步骤:

    • 执行数学计算并将结果保存到名为 math-homework.txt 的文本文件。
    • 使用 upload-artifact 操作上传工件名称为 homeworkmath-homework.txt 文件。

    作业 2 使用上一个作业的结果:

    • 下载在上一作业中上传的 homework 工件。 默认情况下,download-artifact 操作会将工件下载到该步骤执行的工作区目录中。 可以使用 path 输入参数指定不同的下载目录。
    • 读取 math-homework.txt 文件中的值,执行数学计算,并再次将结果保存到 math-homework.txt,覆盖其内容。
    • 上传 math-homework.txt 文件。 此上传会覆盖之前上传的构件,因为它们共用同一名称。

    作业 3 显示上一个作业中上传的结果:

    • 下载 homework 工件。
    • 将数学方程式的结果打印到日志中。

    在此工作流示例中执行的完整数学运算是 (3 + 7) x 9 = 90,工作流程运行运行将会存档它生成的任何构件。

    name: Share data between jobs

    on: [push]

    jobs:
    job_1:
    name: Add 3 and 7
    runs-on: ubuntu-latest
    steps:
    - shell: bash
    run: |
    expr 3 + 7 > math-homework.txt
    - name: Upload math result for job 1
    uses: actions/upload-artifact@v3
    with:
    name: homework
    path: math-homework.txt

    job_2:
    name: Multiply by 9
    needs: job_1
    runs-on: windows-latest
    steps:
    - name: Download math result for job 1
    uses: actions/download-artifact@v3
    with:
    name: homework
    - shell: bash
    run: |
    value=`cat math-homework.txt`
    expr $value \* 9 > math-homework.txt
    - name: Upload math result for job 2
    uses: actions/upload-artifact@v3
    with:
    name: homework
    path: math-homework.txt

    job_3:
    name: Display results
    needs: job_2
    runs-on: macOS-latest
    steps:
    - name: Download math result for job 2
    uses: actions/download-artifact@v3
    with:
    name: homework
    - name: Print the final result
    shell: bash
    run: |
    value=`cat math-homework.txt`
    echo The result is $value

    踩坑记录

    首先看看我的工作流文件,处理部分代码,会发现有一些疑问,怎么和文档提到的不太一样

    name: Deploy Yuque-Hexo Public To Pages

    on:
    repository_dispatch:
    workflow_dispatch:
    push:
    branches: master

    jobs:
    deploy:
    name: Deploy Yuque-Hexo Public To Pages
    runs-on: ubuntu-latest
    env:
    TZ: Asia/Shanghai
    ALGOLIA_ADMIN_API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }}
    YUQUE_TOKEN: ${{ secrets.YUQUE_TOKEN }}
    webpushrKey: ${{ secrets.WEBPUSHR_KEY }}
    webpushrAuthToken: ${{ secrets.WEBPUSHR_AUTH_TOKEN }}

    steps:
    - name: Checkout
    uses: actions/checkout@main
    with:
    ref: master
    fetch-depth: 0

    - name: Setup Node
    uses: actions/setup-node@main
    id: setup-node
    with:
    node-version: "latest"
    check-latest: true
    cache: "npm"

    - name: Catch Dependencies
    uses: actions/cache@main
    id: cache-dependencies
    with:
    path: node_modules
    key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

    - name: Install Dependencies
    if: steps.cache-dependencies.outputs.cache-hit != 'true'
    run: |
    npm ci

    - name: Download Yuque Posts
    uses: dawidd6/action-download-artifact@v2
    with:
    github_token: ${{secrets.GITHUB_TOKEN}}
    name: "Yuque Posts"
    path: "source/_posts"

    - name: Download Yuque Cache
    uses: dawidd6/action-download-artifact@v2
    with:
    github_token: ${{secrets.GITHUB_TOKEN}}
    name: "Yuque Cache"
    path: "yuque"

    - name: Generate
    run: |
    npm i -g hexo-cli yuque-hexo
    npm run yuque
    # npm i -g hexo-cli yuque-hexo
    # mkdir yuque
    # yuque-hexo sync

    - name: Upload Yuque Cache
    uses: actions/upload-artifact@v3
    with:
    name: "Yuque Cache"
    path: yuque
    retention-days: 90

    - name: Upload Yuque Posts
    uses: actions/upload-artifact@v3
    with:
    name: "Yuque Posts"
    path: "source/_posts"
    retention-days: 90

    如果配合package.json看是不是就明显多了

    {
    "name": "ccknbc-blog",
    "version": "latest",
    "private": false,
    "type": "module",
    "scripts": {
    "build": "hexo generate",
    "clean": "hexo clean",
    "deploy": "hexo deploy",
    "server": "hexo server",
    "yuque": "yuque-hexo sync && npm run build && hexo algolia && npm run deploy",
    "github": "npm run build && hexo algolia && npm run deploy"
    },
    "yuqueConfig": {
    "postPath": "/source/_posts/语雀",
    "cachePath": "/yuque/cache.json",
    "lastGeneratePath": "/yuque/lastGeneratePath.log",
    "mdNameFormat": "title",
    "adapter": "markdown",
    "concurrency": "5",
    "timeout": "100s",
    "baseUrl": "https://www.yuque.com/api/v2",
    "login": "ccknbc",
    "repo": "blog",
    "onlyPublished": true,
    "onlyPublic": true
    },

    具体实现思路如下:

    1. 语雀缓存 json 及其时间戳我放在博客根目录yuque这个文件夹里,文章只要放在/source/_posts/下任意目录即可,子目录也行
    2. 上传脚本使用官方的就行,下载脚本得使用action-download-artifact,原因上面也提到了,官方的脚本只能下载在同一工作流运行期间上传的工作流中的工件!而这位作者的脚本默认下载上次运行成功后构建的产物,完美符合我们的需求
    3. 第一次使用只保留上传脚本,注释掉下载脚本,因为没有已成功构建产物,此外在执行yuque-hexo sync 之前因为我没有放在根目录,所以还需要创建文件夹命令mkdir -p yuque否则会报错。后续使用取消注释掉的下载脚本,也可以取消这条命令了,因为加了判断,也可以不取消。
    4. 一定要注意文章放文章目录下,缓存放缓存目录下!不然 hexo 识别到这么大的专属格式json会解析报错卡在了hexo g

    后续更新

    由于原作者以放弃此项目,推荐使用他的新项目同步 @Elog,而使用示例也可查看我的仓库

    文章作者: CC康纳百川
    文章链接: https://blog.ccknbc.cc/posts/yuque-to-hexo/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CC的部落格
    打赏
    • 三合一
      三合一
    • 爱发电
      爱发电

    评论
    \ No newline at end of file diff --git a/privacy-policy/index.html b/privacy-policy/index.html new file mode 100644 index 000000000..dcabf78f7 --- /dev/null +++ b/privacy-policy/index.html @@ -0,0 +1,19 @@ +隐私政策 | CC的部落格

    隐私政策

    本站非常重视用户的隐私和个人信息保护。您在使用网站时,可能会收集和使用您的相关信息。通过《隐私政策》向您说明在您访问 blog.ccknbc.cc 网站时,如何收集、使用、保存、共享和转让这些信息。由于本站性质为个人博客且为静态页面,暂未提供是否接受Cookies弹窗。即使我本人并不想搜集访客过多隐私信息,为了良好的浏览体验,默认启用全部功能,您可暂时使用隐私信息拦截插件去尽可能避免这种追踪。

    如何收集和使用您的个人信息

    网络身份标识信息(浏览器 UA、IP 地址)、您的地理位置信息(具体到城市)、电子邮件地址。

    在您访问时,仅会处于以下目的,使用您的个人信息:

    在访问时,本人仅会处于以下目的,使用你的个人信息:

    • 用于网站的优化与文章分类,用户优化文章
    • 恶意访问识别,用于维护网站
    • 恶意攻击排查,用于维护网站
    • 网站点击情况监测,用于优化网站页面
    • 网站加载情况监测,用于优化网站性能
    • 用于网站搜索结果优化
    • 浏览数据的展示

    统计工具会收集您的访问信息,用于网站的优化与文章分类、恶意访问识别(被动,存储,系统定期清理)

    您应该知道在您访问的时候以下信息会被统计功能使用:

    类型信息
    IP 地址
    国家
    省份
    城市
    运营商
    设备

    如何使用 Cookies 和本地 LocalStorage 存储

    本站为实现简繁切换、深色模式切换等功能,会在您的浏览器中进行本地存储,您可以随时清除浏览器中保存的所有 Cookies 以及 LocalStorage。

    如何共享、转让您的个人信息

    不会与任何公司、组织和个人共享您的个人信息不会将您的个人信息转让给任何公司、组织和个人

    Cookies

    我使用Cookies来保持我的网站和我开发的软件的可靠性,安全性和个性化。当您接受Cookies时,这有助于通过我识别您的身份、记住您的偏好、或提供个性化用户体验来帮助我改善网站。

    如果您对我使用您的个人信息或 Cookies 的方式有任何疑问,请通过 blog@ccknbc.cc 与我联系。

    什么是 Cookies ?

    Cookies是一种小型文本文件,当您访问网站时,网站可能会将这些文件放在您的计算机或设备上。Cookies会帮助网站或其他网站在您下次访问时识别您的设备。网站信标、像素或其他类似文件也可以做同样的事情。我在此政策中使用术语“Cookies”来指代以这种方式收集信息的所有文件。

    Cookies提供许多功能。例如,他们可以帮助我记住您喜欢深色模式还是浅色模式,分析我网站的效果。

    大多数网站使用 Cookies 来收集和保留有关其访问者的个人信息。大多数 Cookies 收集一般信息,例如访问者如何到达和使用我的网站,他们使用的设备,他们的互联网协议地址(IP 地址),他们正在查看的页面及其大致位置(例如,我将能够认识到您正在从北京访问我的网站)。

    Cookies 的目的

    我将 Cookies 分为以下类别:

    用途说明
    授权您登录我的网站时,我可通过 Cookie 提供正确信息,为您打造个性化的体验。例如: Cookies 会告知您通过搜索引擎搜索的具体内容来改善文章的标题优化关键词、或者创建更符合您搜索需求的文章内容。
    安全措施我通过 Cookies 启用及支持安全功能,监控和防止可疑活动、欺诈性流量和违反版权协议的行为。
    偏好、功能和服务我使用功能性 Cookies 来让我记住您的偏好,或保存您向我提供的有关您的喜好或其他信息。
    网站性能、分析和研究我使用这些 Cookies 来监控网站性能。这使我能够通过快速识别和解决出现的任何问题来提供高质量的体验。

    我的网站上的第三方 Cookies

    我还在我的网站上使用属于上述类别的第三方 Cookies,用于以下目的:

    • 帮助我监控网站上的流量;
    • 识别欺诈或非人为性流量;
    • 协助市场调研;
    • 改善网站功能;
    • 监督我的版权协议和隐私政策的遵守情况。
    第三方服务商用途
    Algolia Docsearch用于提供站内搜索服务,并辅助分析用户感兴趣内容
    Instatus用于离线页面展示网站运行状态,提示用户网站状态
    Microsoft CLARITY用于国内用户统计站内访问情况,文章优化,恶意攻击排查
    Google Analytics用于国外用户统计站内访问情况,文章优化,恶意攻击排查
    leancloud.app在用户同意本站收集部分信息后,作为评论系统存储的数据库
    Webpushr在用户同意订阅推送后,作为推送服务提供商需存储用户的定制化数据
    follow.it在用户同意订阅推送后,作为推送服务提供商需存储用户的定制化数据

    对此 隐私政策的更改

    我可能对此 Cookies 政策所做的任何更改都将发布在此页面上。如果更改很重要,我会在博客首页明确指出该政策已更新。

    最后修订时间:2023 年 6 月 10 日 23:22

    评论
    \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 000000000..521b13c83 --- /dev/null +++ b/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Disallow: /categories/ +Disallow: /tags/ +Sitemap: https://blog.ccknbc.cc/baidusitemap.xml +Sitemap: https://blog.ccknbc.cc/sitemap.xml \ No newline at end of file diff --git a/rss.xml b/rss.xml new file mode 100644 index 000000000..74f8d4af5 --- /dev/null +++ b/rss.xml @@ -0,0 +1 @@ +CC的部落格https://blog.ccknbc.cc/https://cdn1.tianli0.top/gh/ccknbc-backup/cdn/logo/logo.pngCC的部落格https://blog.ccknbc.cc/CC的部落格,CC康纳百川的小窝,与你分享二三事CC康纳百川Sun, 25 Jun 2023 12:44:00 GMThttps://blog.ccknbc.cc/你以为 AddThis 只是个分享工具吗?https://blog.ccknbc.cc/posts/the-real-addthis/https://blog.ccknbc.cc/posts/the-real-addthis/Sat, 15 May 2021 13:00:00 GMT本文介绍了 AddThis 的使用本文首发在语雀,自动同步更新至CC 的部落格

    本文作废

    Notice of Termination of AddThis Services.

    What’s Changing?

    As part of a periodic product portfolio review, Oracle has made the business decision to terminate all AddThis services effective as of May 31, 2023.

    Key Dates

    Existing AddThis users can expect that after May 31, 2023:

    • the user must immediately cease its use of AddThis services, and promptly remove all AddThis related code and technology from its websites;
    • AddThis buttons may disappear from the user’s websites;
    • the AddThis dashboard associated with the user’s registration for AddThis, and all support for AddThis services, will no longer be available;
    • all features of AddThis configured to interoperate with user’s websites, any other Oracle services, or any third-party tools and plug-ins will no longer function.

    Oracle thanks you for your attention and understanding in this matter, and for the many years of allowing Oracle to provide this service to you.

    How Do I Uninstall the AddThis Button?

    If you’ve copied and pasted the code into your website, go back into the code and look for and , then delete these lines and any code between them. If you’ve used another method to install AddThis on your page, please contact us and we’ll be happy to help you.

    总结:终止服务,主题已移除

    Butterfly 如何使用

    打开 AddThis 官网,标语是 Turn your visitors into engaged customers. 听起来是个营销工具,但主题集成的时候选择了它,并且没有做特别说明,只是让我们找到 pub-id ,并没有说如何配置

    实际上要想和 AddToAny 或者 sharejs 一样使用文章内分享,我们得在控制台添加 Tools,就像下图所示然后选择行内工具后面样式部分就根据自己喜好和需求按钮多少,在哪些页面显示等来自行配置啦。比如我还同时选择了,自动展开分享按钮。而且他能很好的自适应,并且后台修改之后我们博客无需任何操作即可更新。

    其他工具

    但还有其他工具也很好用,比如你点进文章来之前,应该有弹窗提示你要阅读隐私政策,实际上这是链接推广工具的活用。再比如放在顶栏作为临时公告,并且都有很好的自适应人性化选择,你下滑就会收起来,上滑再弹出。同样如果你是文章页或者订阅页面,因为我配置了仅在这些页面显示,会弹出一个订阅文章更新弹窗,这里收集邮件工具派上了用场,并且与 Mailchimp 配合完成了这项工作,至于配置邮件订阅,可以查看之前的文章 为你的 Hexo 博客添加邮件订阅不过为了邮件订阅,我同样整合到了 Tidio,详情见订阅页面。当然如果你也在乎其他平台的关注数量,可以使用关注按钮来实现推广效果,文章推荐和打赏这里还是建议使用主题自带的就好。此外它还配有统计分析工具(这里强烈推荐您阅读 隐私政策),以帮助你实现更好的内容转化。所以结合起来正常情况下我开起了五个工具当需要发布临时公告时,我会根据重要程度选择左下角或者顶栏就免费来说,他做的很不错了,相比于专门做弹窗的 poptin 似乎更简单的与 mailchimp 集成,但毕竟术业有专攻,比弹窗肯定不如人家,不过白嫖来说已经够了,我也不用使用 snackbar 刷新 jsd 缓存来实现临时公告了。而我现在重新使用了 webpushr 来实现浏览器通知,不管是否订阅,我均可以发送公告,并可保留最近 3 条公告,然后这就涉及到了空间利用率和用户体验的问题,所以我就得考虑关闭一些小部件,比如邮件订阅弹窗(据说会影响搜索引擎权重),还有分享按钮。电脑上无所谓,手机上显得有点挤(不过可以选择根据设备或者宽度自适应是否显示),即使我放在右下角,分享按钮放在左下角。所以我在公告栏加入了邮件订阅表格,并添加链接导向订阅页,但毕竟也没人订阅,还是链接导向订阅页面吧。

    ]]>
    工具工具https://blog.ccknbc.cc/posts/the-real-addthis/#post-comment
    Hexo浏览器定向推送文章更新https://blog.ccknbc.cc/posts/hexo-webpushr-notification/https://blog.ccknbc.cc/posts/hexo-webpushr-notification/Tue, 04 Oct 2022 16:00:00 GMT这一次,CC的部落格可以根据读者订阅主题定向推送了,并且实现了NPM插件化查看本文语雀版本【首发】,自动同步更新至CC 的部落格

    两年前,我刚开始使用Hexo的时候,写了一篇文章简单浏览器更新推送的实现,最近登录webpushr控制台,发现其支持按话题topic指定推送了,而原来的插件一直没有更新,且对个人的写作习惯不是很友好,所以对原插件进行了修改,并发布到了NPM

    欢迎大家前往订阅页面选择合适的订阅方式,关于邮件订阅,现已支持分类订阅

    安装

    推荐使用 npm 以插件形式安装

    npm i hexo-webpushr-notification

    自定义修改

    当然你也可以自定义修改webpushr.js文件后,再安装相关需要依赖,然后将文件放到Hexo/scripts/目录下即可正常运行,CC 本人亦是如此对于 0.2.0 以上版本,您只需要在 Hexo 所在目录安装 axios 即可,这样测试相较于安装 GitHub 更方便(以及欢迎 PR )

    npm i axios

    使用

    在你的 Hexo 根目录配置文件 _config.yml中添加如下内容,可按需配置,建议前往 README 查看最新配置

    webpushr:
    enable: true

    webpushrKey: "webpushrKey"
    webpushrAuthToken: "webpushrAuthToken"
    # 出于安全考虑,建议将上述两个重要参数添加至系统全局环境变量,并删除或注释掉此处配置
    # 否则可在网页端向访问者或订阅用户发送推送 https://www.webpushr.com/api-playground
    # 例如GitHub Actions环境变量配置,参数名不变,密钥名自定义,可参考如下
    # env:
    # webpushrKey: ${{ secrets.WEBPUSHR_KEY }}
    # webpushrAuthToken: ${{ secrets.WEBPUSHR_AUTH_TOKEN }}
    # 如果您的仓库私有,则无需担心此问题

    trackingCode: "trackingCode"
    icon: "https://.../192.png" # 必须为 HTTPS 以及 192*192 png图片
    # auto_hide: false # 默认为 1,代表true,即自动隐藏
    # sort: "date" # 默认为updated,即只要最新文章更改了更新时间即推送新文章,改为date即文章第一次发布时间
    # delay: "0" # 延时推送,考虑到CDN缓存更新,默认定时为在 hexo d 10分钟后推送,单位为分钟(最短延时为5分钟,设置 0 则会立即推送)
    # expire: "15d" # 推送过期时长,默认值为7天,格式如下:'5m'代表5分钟,'5h'代表5小时, '5d'代表5天.
    # image: # 默认为文章封面,Front-matter 属性为'cover'(butterfly主题友好选项),如果您没有定义默认封面或此属性,请在这里设置默认image
    action_buttons: # 如果你需要额外自定义按钮 可按照如下格式:
    - title: 阅读全文 # 当 title 未配置时 默认值为 “前往查看”
    # url: # 当 url 未配置时 默认值为 最新文章链接
    - title: 订阅页面
    url: https://blog.ccknbc.cc/sub/
    # 当 action_buttons 未定义时也默认保留了一个“前往查看”按钮,除非设置为 false
    # action_buttons: false # 当设为 false 则不显示额外的按钮,因为隐藏按钮即为当前文章链接

    # 以下配置为按订阅主题推送给不同订阅用户,请按照数组形式,一一对应,具体位置请看使用文档
    categories: [工作, 博客, 工具, 生活, 音乐, 学习]
    segment: ["484223", "484224", "484225", "484226", "484227", "484229"]
    endpoint: segment # 可选配置 all / segment / sid
    # 默认为 segment,即根据不同主题推送细分,同时配置上述选项
    # 例如 all,即推送至所有用户;针对本地测试,建议只推送给单个用户即自己,同时设置下方的 sid 值
    # 您也可以将segment 设置为 all-users 对应的ID,同样也可以实现推送至所有用户
    sid: "119810055" # 单个用户ID 可在控制台查看 https://app.webpushr.com/subscribers


    # 此外,在文章 Front-Matter 处
    # 可覆盖 auto_hide 和 expire 配置,针对需要特别提醒文章可以设置不自动隐藏及过期时间延长等操作
    # 以及可指定schedule参数(例如:schedule: 2022-10-01 00:00:00),定时推送
    # 当文章头设置 webpushr: false 时,可关闭本篇文章推送,此参数主要防止久远文章更改更新时间后自动推送
    1. 前往 webpushr 控制台获取如下参数,注册的时候可能会遇到一点困难,中国大陆用户需要科学上网来加载验证服务)
    2. 关于注册及一些具体内容,可以看之前的文章 简单浏览器更新推送的实现
    3. 依次点击 Integration > REST API Keys,即可看到你的webpushrKeywebpushrAuthToken
    4. 依次点击 Setup > TrackingCode,可以看到如下代码
    <!-- start webpushr tracking code -->
    <script>(function(w,d, s, id) {if(typeof(w.webpushr)!=='undefined') return;w.webpushr=w.webpushr||function(){(w.webpushr.q=w.webpushr.q||[]).push(arguments)};var js, fjs = d.getElementsByTagName(s)[0];js = d.createElement(s); js.id = id;js.async=1;js.src = "https://cdn.webpushr.com/app.min.js";
    fjs.parentNode.appendChild(js);}(window,document, 'script', 'webpushr-jssdk'));
    webpushr('setup',{'key':'BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58' });</script>
    <!-- end webpushr tracking code -->

    最后一行BKOlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLvbjpdw8x2GmFmi1ZcLTz0ni6OnX5MAwoM58 就是你的 trackingCode

    注意:因权限问题,本地测试时(hexo s)可能不会显示弹窗,但如果你配置了小铃铛,小铃铛会显示

    额外配置

    因官方 sw 脚本注册后,我们无法注册自己的 sw 脚本,但官方提供了配置,方便我们使用 sw 的缓存,拦截请求等功能

    首先在配置项中添加 sw_self: true 配置,开启自行注册 sw(默认用户不用添加或者设为 false

    webpushr:
    sw_self: true

    另外,你还需要在你的脚本文件(例如sw.js)中引入

    importScripts('https://cdn.webpushr.com/sw-server.min.js');

    完成这些你就可以自行注册你的sw脚本了,如果你需要了解如何编写或注册service worker脚本,可以参考以下文章或项目hexo-swpp
    Service Worker
    clientworker
    Workbox

    自定义

    个人建议将控制台右上角小铃铛 🔔 里全部配置一遍以获得更好的效果

    你需要自定义一些参数才可以使用根据不同主题,按照订阅者订阅话题推送功能(目前根据个人需求是这个设置,默认行为为当未匹配到对应分类时不推送文章,而不是向所有用户推送文章,当然你也可以配置目标为所有用户)

    在控制台,点击Setup>Opt-In Prompt ,向下滑动打开Enable Topics(小铃铛样式无此选项,因此推荐您使用前两种样式),并新增几个主题,对应你想推送的文章分类即可

    然后点击Users>Segments ,即可获取对应的segment关系,依次填入配置项即可

    工作原理

    当你运行hexo generate插件会在public 目录生成 newPost.json 这样一个文件. newPost.json 包含了一些你想推送的新文章相关信息,示例格式如下

    {
    "title": "Hexo浏览器定向推送文章更新",
    "updated": "2023-04-22T20:25:00+08:00",
    "message": "这一次,CC的部落格可以根据读者订阅主题定向推送了,并且实现了NPM插件化",
    "target_url": "https://blog.ccknbc.cc/posts/hexo-webpushr-notification/",
    "image": "https://pic1.afdiancdn.com/user/8a7f563c2e3811ecab5852540025c377/common/d2a947d48815ed24936a919873b97841_w1366_h768_s31.png",
    "categories": ["博客"],
    "schedule": "2023-06-13T15:16:41.187Z",
    "expire": "7d",
    "auto_hide": "1"
    }

    而他的来源就是我们在文章开头Front-Matter自定义的那些属性,而本插件针对Butterfly主题做了针对性修改,您也可以在您的模板文件目录下修改文章模板文件(Hexo/scaffolds/post.md),主要针对性参数如下

    date:
    updated:
    schedule: 对应配置项中定时推送时间
    auto_hide: 对应配置项中是否自动隐藏
    expire: 对应配置项中过期时间
    categories: 文章分类
    description: 对应配置项中message,即文章描述
    cover: 对应配置项中image,默认选取文章封面

    如果你的主题不是采用默认的date updated 参数,记得补充,因为这是判断最新文章的依据

    如果你习惯了使用截断的方式,也无需配置description继续使用,示例如下,注意<!-- more -->

    ---
    title: Hexo使用Web Push Notification 浏览器通知推送
    tags:
    - hexo
    - 服务器推送技术
    - push notifications
    categories:
    - 开发
    comments: true
    abbrlink: 98ae9e55
    date: 2020-02-26 10:00:00
    ---

    Web Push Notification 是怎么工作的?个人博客为什么要使用它?如何使用它?

    <!-- more -->

    当执行 hexo deploy命令时,插件会比较在线版本和本地版本newPost.json中最新文章更新时间是否一致,如果不同,则插件将推送最新文章更新通知(默认为十分钟后推送)

    注意:如果您是第一次使用本地测试应该看到

    INFO  无文章更新 或 为首次推送更新

    这是正常现象,因为此时你的网站还没有newPost.json这个文件,后续有更新时将正常推送,你可以先推送一次,再修改更新时间测试一次,当然建议测试目标选择自己,即 sid 选项配置

    当然如果您在使用过程中有什么问题或遇到了 Bug 也欢迎随时在评论区或issues反馈,当然因为本人是菜鸡,所以有大佬 PR 最好了

    推送效果

    因为我是通知自动隐藏后才截图,所以大致效果如下所示

    后续计划

    • 兼容自定义Service Work的功能,因为webpushr-sw.js优先注册的原因,只能有一个 sw注册,无法注册自己编写脚本。
    • 支持参数更多的可自定义,启用或关闭。例如不延时,立即发送;不显示按钮(因为默认就是跳转到文章)等
    • 目前的判断逻辑,虽然可以根据更新时间来判断,但如果很久之前的文章翻新,只要更新时间最新,也会触发推送,主要针对 updated 方式,还没想到好的解决办法,目前就是确认需要推送才更改更新时间咯
    ]]>
    博客博客工具https://blog.ccknbc.cc/posts/hexo-webpushr-notification/#post-comment
    2023《好好》线上演唱会https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/Wed, 08 Mar 2023 12:30:00 GMT刘若英X苏慧伦X丁当X白安 2023《好好》线上演唱会 Song About You live in the sky 2023

    版权归属 台湾 相信音乐

    刘若英 X 苏慧伦 X 丁当 X 白安

    2023《好好》线上演唱会

    Song About You live in the sky 2023

    歌单一览

    已在视频中标出


    苏慧伦 part

    0:30 鸭子

    4:27 被动

    8:18 说话

    9:09 严重

    13:12 说话

    13:24 恋恋真言

    17:17 在我生命中的每一天 feat.丁当


    丁当 part

    21:58 开头

    22:39 夜猫

    26:13 花火

    30:18 说话

    31:07 猜不透

    35:12 说话

    37:25 女字旁

    41:56 我爱他


    白安 part

    46:54 不够特别的我不要

    51:41 刚好

    56:01 说话

    56:39 是什么让我遇见这样的你

    1:00:39 没有人写歌给你过吧

    1:05:39 让我逃离平庸的生活


    刘若英 part

    1:10:25 所有相爱的人啊

    1:14:28 成全

    1:18:57 说话

    1:20:55 固执

    1:25:47 缩影

    1:29:30 talking feat.白安

    1:31:20 妈妈 feat.白安

    1:35:51 后来

    1:40:52 快乐天堂 feat.苏慧伦、丁当、白安


    女加上子 每个女子生而为好

    该对自己好 该好好疼爱自己

    女子女子 就是好好

    好歌相伴 好上加好

    《好好》线上演唱会

    一场女子们的闺密音乐聚会

    宜尽兴 宜微醺 宜舒心 宜走心

    妳有多久没有好好跟自己说说话了?

    妳有多久没有好好聆听心底声音了?

    妳有多久没有好好跟好友聊聊天了?

    妳有多久没有好好欣赏美好事物了?

    女子,要好好去爱,更要好好爱自己。

    「3 月 8 日」是一年一度的「国际妇女节」 (International Women’s Day),提醒每个女子要爱自己,更能去爱别人、去爱这个世界。 在这个这个专属于女子的节日,刘若英 X 苏慧伦 X 丁当 X 白安,四个女子的美好相遇,要在 38 妇女节的周三夜,以音乐用心地打造出一场属于每个你的 “Lady’s Night”,你可以与你自己,也可以与好闺密们,一起好好享受、好好尽欢、好好聆听一首首动人的女子心声。

    如水 如石 如光 如树

    一场音乐与自然的飨宴

    将美好谱写 如歌而行

    当音乐遇见自然 当内心遇见自己

    美的时节 好的相遇

    女子女子 好好与你以歌相聚

    「女」加上「子」等于「好」,「女子」加上「女子」就是「好好」,好上加好! 「好好女声」刘若英、苏慧伦、丁当、白安,春暖花开时节献唱,,以歌相聚在《好好》线上演唱会,不仅渲染多首个人经典好歌,彼此间更有精彩的合唱新火花! 《好好》演唱会以「女野」概念,结合「水、石、光、树」为主题,女子在自然旷野里吟唱,呈现出如水之柔美、如石之坚强、如光之魔幻、如树之实在的演唱氛围。

    新的一年一切都在慢慢变好,刘若英、苏慧伦、丁当、白安,四美女子以美好歌声陪伴每个认真生活、认真爱的女子,一起告别因疫情闷久的坏坏情绪,迎接温暖美丽的好好心情

    视频版

    流媒体平台

    QQ 音乐 | 网易云音乐 | 酷狗音乐 | 酷我音乐 | 咪咕音乐 | 汽水音乐

    ]]>
    音乐台湾音乐https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/#post-comment
    Hexo Butterfly Algolia 搜索的使用https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/Tue, 11 May 2021 03:00:00 GMT本文介绍了 Hexo Butterfly 主题下 Algolia 搜索的使用本文介绍了 Hexo Butterfly 主题下 Algolia 搜索的使用

    本文首发在语雀自动同步更新至CC 的部落格

    注册账号

    前往 Algolia 官网注册一个账号,新建 应用和 index数据中心建议选择新加坡或香港,当然根据你自己情况而定

    安装插件

    npm install hexo-algolia --save
    npm install hexo-algoliasearch --save

    分别是 hexo-algoliahexo-algoliasearch,他们的介绍分别为

    Index your hexo website content to Algolia Search.
    🔎 A plugin to index posts of your Hexo blog on Algolia

    也就很明显了,如果你想要全站搜索可选择前者,如果你只想搜索文章两者兼可。但前者不能将文章内容作为索引上传(其实老版本是支持的,但因为索引大小限制,在新版本取消索引了文章内容),后者目前仍可全文上传。然后就是 HEXO 配置文件中添加以下内容,下文基本以 hexo-algoliasearch 为例,因为我个人认为访客只会搜文章吧(事实上是搜索根本没人用,毕竟也根本没人访问),hexo-algolia 可查看官方文档,注意配置和命令的区别

    _config.yml :

    algolia:
    appId: "Z7A3XW4R2I"
    apiKey: "12db1ad54372045549ef465881c17e743"
    adminApiKey: "40321c7c207e7f73b63a19aa24c4761b"
    chunkSize: 5000
    indexName: "my-hexo-blog"
    fields:
    - content:strip:truncate,0,500
    - excerpt:strip
    - gallery
    - permalink
    - photos
    - slug
    - tags
    - title

    为了保险,识别到插件,还可以加入以下内容

    plugins:
    - hexo-algoliasearch

    去主题配置文件打开 Algolia 搜索,记得关闭本地搜索,二者只能取其一!

    _config.butterfly.yml :

    # Algolia search
    algolia_search:
    enable: true
    hits:
    per_page: 3

    # Local search
    local_search:
    enable: false

    然后来看以下具体的参数配置获取方式appIdapiKeyadminApiKey可在 API Keys 页面获取,注意保管好你的 Admin Key,不要让其他人知道,不建议直接写在配置中对于 Windows 系统,如果你不想每次都进行设定变量操作,可以添加ALGOLIA_ADMIN_API_KEY到系统的环境变量中而 hexo-algolia 插件环境变量名称为 HEXO_ALGOLIA_INDEXING_KEY 注意根据对应的文档更改,当然也可以使用命令行工具

    # Windows
    ## 微软的 powershell)
    $env:ALGOLIA_ADMIN_API_KEY = ""

    ## cmd
    建议不用 cmd,正经人不用 cmd

    # Linux
    ## sh/bash
    export ALGOLIA_ADMIN_API_KEY=

    ## fish
    set -xg ALGOLIA_ADMIN_API_KEY ""

    如果你和我一样使用的自动部署,例如 Github Actions,你可以在工作流中一开始或者对应的步骤添加环境变量,记得 Secrets 中也要添加哦

    jobs:
    deploy:
    name: Deploy Hexo Public To Pages
    runs-on: ubuntu-latest
    env:
    TZ: Asia/Shanghai
    ALGOLIA_ADMIN_API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }}

    或者使用

    export ALGOLIA_ADMIN_API_KEY=…
    export HEXO_ALGOLIA_INDEXING_KEY=…

    indexName 即你开始新建的索引名称其他内容保持默认即可,但对于fields

    配置示例

    这里选择不截取上传全文,并且删除 html 标签,只留下有用的搜索内容

    fields:
    - content:strip
    - excerpt:strip
    - gallery
    - permalink
    - photos
    - slug
    - tags
    - title

    但对于博客来说,没人会按照 tags photos(或者 cover)来搜索吧,所以有些内容不必要上传,并如果你和我一样有多个镜像站,在不改源码(algolia.js)的情况下,不会使用 permalink 而使用 path(改源码可以使用 slug,但没必要),并且只留下必要的内容,如下所示:

    algolia:
    appId: "947RX7HP3E"
    apiKey: "9114b3fa2a3307b2cc8eec7e3ae5a8ea"
    chunkSize: 5000
    indexName: "ccknbc-blog"
    fields:
    - path
    - title
    - content:strip

    这样有了标题,全文内容,路径即可在不同镜像站找到对应的页面,而不是跳到主站,当然你选择跳到主站无可厚非。

    使用命令

    hexo algolia
    而在这之前还需要hexo g生成文件
    所以具体使用命令就是
    hexo cl && hexo g && hexo algolia
    或者在未安装 HEXO CLI 的情况下使用以下命令
    npm run clean && npm run build && hexo algolia -n && gulp

    可选配置

    是否删除之前建立好的索引重新建立索引?

    hexo algolia -n
    或者
    hexo algolia --no-clear

    注意查看命令行输出信息,然后去官网检查索引是否生成事实上到这里已经可以获得下图所示的搜索效果(这是冰老师博客的效果,它使用的是 hexo-algolia,毕竟有关于我界面)

    Algolia 配置

    这里不细节讲,你可以查阅官方文档,虽然有些过时的参数,但结合 Upgrade from v2 to v3 还是勉强能用,蝴蝶已经做好了高亮标题,虽然会查询文章内容,但并不会高亮文章内容节选,我们要做的就是修改部分 js 内容,并对应的设置好 Algolia,以便按照我们要求的优先顺序展示搜索结果,而不是默认的很奇怪的排序,毕竟针对中文分词他是一个一个分不能按照英语那样,针对英文我们可以开启分词查询,驼峰查找而不是盲目的匹配整个单词,并且允许拼错字母或汉字的情况存在,这些都是一个搜索系统要考虑的问题。然后针对搜索速度,我们可以对文章内容进行切片或者属性的刻画,但 V2 所支持的功能实在太少,派的上用场的大概就是 匹配的字词内容,匹配度,匹配内容的摘录(默认 10 个字词),还有高级搜索用法的启用。

    JS 修改

    主题 4.0.0 以下版本

    到这里还没有结束,如果你这样操作就会有一个问题,假设你的访问流量很大,有很多人用搜索功能,那么免费的 1 万次搜索额度可能不够一个月的使用,需要按下ENTER键再执行搜索而不是实时搜索,因此可以稍作修改(blog\themes\butterfly\source\js\search\algolia.js) js 的部分内容,不想动源码的可以保存到其他与主题不冲突的路径,然后更换 CDN 地址即可主要修改以下内容,然后就是排版问题改了改位置,不喜欢的可以不改,很直白就不用过多解释了,这样就可获得和本博客一样的搜索效果了

      search.addWidget(
    instantsearch.widgets.searchBox({
    container: '#algolia-search-input',
    reset: false,
    magnifier: false,
    + searchOnEnterKeyPressOnly: true,
    placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder
    })
    )
    search.addWidget(
    instantsearch.widgets.hits({
    container: '#algolia-hits',
    templates: {
    item: function (data) {
    const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
    return (
    '<a href="' + link + '" class="algolia-hit-item-link"><b>' +
    data._highlightResult.title.value + '</b><br>'
    + + data._snippetResult.contentStrip.value + '<br>( 匹配字词 : '
    + + data._highlightResult.contentStrip.matchedWords + ' ) | ( 匹配等级 : '
    + + data._highlightResult.contentStrip.matchLevel + ' )</a>'
    )
    },

    主题 4.0.0 以上版本

    已经升级到 V4 版本,那么一些特性就可以使用了,修改内容其实差不多,只是建议对于第 87 行的页数限制,主要是为了手机上排版美观,不会转到下一行,但是这样会有一个问题,如果结果超过 5 页,那么将无法显示,最后一页代表第 5 页,所以我个人会选择删掉这个参数限制,同时合并删除了部分代码,以及使用 widget 的 powerby 组件而不是官方的 svg 代码解决方案。另外因为新版官方的每次访问网站都会有一次全局请求,这在消耗免费额度的同时,也影响网站加载的速度,所以修改默认行为为按下回车后再请求同样的部分参数发生了改变(L55-59),可以自行比对或查看官方文档,也可以直接引用我的

    特别提一嘴官方切片方式对我来说 140 个字太长了,所以如果可以接受就用官方的,不用做其他更改,但想要和我的显示方式一样,就注意配置好切片,默认是 10 个词符,毕竟有现成的切片高亮处理可以用,就没必要再来一次了

    另外,新版浏览器支持搜索并定位高亮处理,所以对跳转链接也做了处理,算是弥补了一点不能精准定位的缺陷,比如点击如下链接它会跳转到搜索结果对应的位置,至于前后匹配多少字符你们自行修改,但也是处于不太好用的状态,毕竟是分片还是有点奇怪,对英文来说应该是单词识别,只是中文恰巧是另一标准,单字变成了词

    #:~:text=勿滥用-,表情,-符号和

    CDN:
    # search
    algolia_js: https://cdn.jsdelivr.net/gh/CCKNBC/ccknbc.github.io/js/search/algolia.js
    window.addEventListener("load", () => {
    const openSearch = () => {
    const bodyStyle = document.body.style;
    bodyStyle.width = "100%";
    bodyStyle.overflow = "hidden";
    btf.animateIn(document.getElementById("search-mask"), "to_show 0.5s");
    btf.animateIn(
    document.querySelector("#algolia-search .search-dialog"),
    "titleScale 0.5s"
    );
    setTimeout(() => {
    document.querySelector("#algolia-search .ais-SearchBox-input").focus();
    }, 100);

    // shortcut: ESC
    document.addEventListener("keydown", function f(event) {
    if (event.code === "Escape") {
    closeSearch();
    document.removeEventListener("keydown", f);
    }
    });
    };

    const closeSearch = () => {
    const bodyStyle = document.body.style;
    bodyStyle.width = "";
    bodyStyle.overflow = "";
    btf.animateOut(
    document.querySelector("#algolia-search .search-dialog"),
    "search_close .5s"
    );
    btf.animateOut(document.getElementById("search-mask"), "to_hide 0.5s");
    };

    const searchClickFn = () => {
    document
    .querySelector("#search-button > .search")
    .addEventListener("click", openSearch);
    };

    const searchClickFnOnce = () => {
    document
    .getElementById("search-mask")
    .addEventListener("click", closeSearch);
    document
    .querySelector("#algolia-search .search-close-button")
    .addEventListener("click", closeSearch);
    };

    const algolia = GLOBAL_CONFIG.algolia;
    const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName;
    if (!isAlgoliaValid) {
    return console.error("Algolia setting is invalid!");
    }

    const search = instantsearch({
    indexName: algolia.indexName,
    searchClient: algoliasearch(algolia.appId, algolia.apiKey),
    searchFunction(helper) {
    helper.state.query && helper.search();
    },
    });

    const configure = instantsearch.widgets.configure({
    hitsPerPage: algolia.per_page || 5,
    });

    const searchBox = instantsearch.widgets.searchBox({
    container: "#algolia-search-input",
    showReset: false,
    showSubmit: false,
    searchAsYouType: false,
    placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
    showLoadingIndicator: true,
    });

    const hits = instantsearch.widgets.hits({
    container: "#algolia-hits",
    templates: {
    item(data) {
    const link = data.permalink
    ? data.permalink
    : GLOBAL_CONFIG.root + data.path;
    const content = data._snippetResult.contentStrip.value;
    return `
    <a href="${link}#:~:text=${content.substring(
    content.indexOf("<mark>") - 3,
    content.indexOf("<mark>")
    )}-,${content.substring(
    content.indexOf("<mark>") + 6,
    content.indexOf("</mark>")
    )},-${content.substring(
    content.indexOf("</mark>") + 7,
    content.indexOf("</mark>") + 10
    )}" class="algolia-hit-item-link">
    <b>${data._highlightResult.title.value || "no-title"}</b>
    <br>${content}</br>
    匹配字词: <em><mark>${
    data._highlightResult.contentStrip.matchedWords
    }</mark></em> | 匹配等级: <em><mark>${
    data._highlightResult.contentStrip.matchLevel
    }</mark></em>
    </a>`;
    },
    empty: function (data) {
    return (
    '<div id="algolia-hits-empty">' +
    GLOBAL_CONFIG.algolia.languages.hits_empty.replace(
    /\$\{query}/,
    data.query
    ) +
    "</div>"
    );
    },
    },
    });

    const stats = instantsearch.widgets.stats({
    container: "#algolia-info > .algolia-stats",
    templates: {
    text: function (data) {
    const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
    .replace(/\$\{hits}/, data.nbHits)
    .replace(/\$\{time}/, data.processingTimeMS);
    return `<hr>${stats}`;
    },
    },
    });

    const powerBy = instantsearch.widgets.poweredBy({
    container: "#algolia-info > .algolia-poweredBy",
    });

    const pagination = instantsearch.widgets.pagination({
    container: "#algolia-pagination",
    totalPages: algolia.totalPages,
    templates: {
    first: '<i class="fa-solid fa-angle-double-left" title="第一页"></i>',
    last: '<i class="fa-solid fa-angle-double-right" title="最后一页"></i>',
    previous: '<i class="fa-solid fa-angle-left" title="上一页"></i>',
    next: '<i class="fa-solid fa-angle-right" title="下一页"></i>',
    },
    });

    search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]); // add the widgets to the instantsearch instance

    search.start();

    searchClickFn();
    searchClickFnOnce();

    window.addEventListener("pjax:complete", () => {
    getComputedStyle(document.querySelector("#algolia-search .search-dialog"))
    .display === "block" && closeSearch();
    searchClickFn();
    });

    window.pjax &&
    search.on("render", () => {
    window.pjax.refresh(document.getElementById("algolia-hits"));
    });
    });

    效果预览

    (这个是因为我修改了源码,实际上也能通过修改 JS 实现,但大多数人不会关心这些搜索小贴士)对于中文它当作单字匹配允许拼写错误

    特别说明

    因两个月前已申请通过,本博客已切换至不限搜索次数的DocSearch!同时也加入了开源计划,但因为 10DSN 太香了,虽然 instantsearch 可玩性更好,但我也只申请了 200k/月的额度(虽然可以增加),所以为了即时搜索我还是选择了白嫖,而且设定为每天自动爬取的话,省去了生成索引上传的这一步骤,节省了自动部署的时间。而且爬取到数据后,前端我并非一定要使用 docsearch 方案,用 instantsearch 配合其他插件也不是不可以。

    ]]>
    工具工具https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/#post-comment
    你的公共电视https://blog.ccknbc.cc/posts/about-pts/https://blog.ccknbc.cc/posts/about-pts/Sun, 07 Aug 2022 05:16:00 GMT作为一个大陆人,时常希望有一个独立于官媒的非自媒体存在,而这次,我想和大家聊一聊这个台湾媒体中特别的存在【公共电视】查看本文语雀版本【首发】,自动同步更新至CC 的部落格

    作为一个大陆人,时常希望有一个独立于官媒的非自媒体存在,你可能会提到傲娇的“六公主”;而这次,我想和大家聊一聊这个台湾媒体中特别的存在【公共电视】

    关于公视

    公视使命

    “公共电视”是一种电视制度, 在传播学理上有其定义与任务。

    它必须有自己的频道、 自己的电台、 有自己的节目政策, 所有的播出都是为了服务公众, 提供公众必须的资讯为主要功能。

    因此, 公视和宣导政令的国家电视不同, 和以广告、收视率好坏来取决节目内容的商业电视不同。

    公视属于全体民众, 不专为政府或某一政党服务; 不以营利为目的, 也不受商业或利益团体左右, 公共电视,顾名思义, 是接收全民付託, 以服务公共利益为宗旨的电视媒体。

    那【公视】与 【台视】【华视】【民视】【中视】等带有明显倾向色彩的电视台有什么不同呢?台湾虽然本土面积不大,但却拥有者 300 多家电视台,在这里开电视台,真的就是靠财团砸钱。你或许知道【中视】与【中天】的老板是同一个,没错就是“旺旺”,因此你可以经常看到记者手持两家电视台的麦克风,一条新闻两台播,这样比较省钱啦,而因为具有明显的亲中色彩,两家在岛内的收视率或许并没有那么高,【中天新闻台】也只是被迫改为网络播出。

    台湾公广集团有:公共电视,PTS Taiwan (English),公视台语台,中华电视公司,客家电视台

    那你也就可以理解为什么【公视】经常称呼【华视】为友台,一开始我们有提到过,它并不在乎自己的收视率,因此不论你何时切到公视,都是没有广告的,这与其他频道是一个明显的区别;那上面提到过运营一家电视台真的很烧钱,公视为什么每年还有那么多自制剧,资金链从哪来?

    经费来源

    世界上其他国家也有公共媒体,不同于 NHK, BBC,公民需要每年像这些公共媒体强制性缴纳费用,公视经费主要来源有以下

    1. 公视基金会第一年得到的政府捐赠 为十二亿元新台币, 自筹款为三亿元。依据公共电视法, 政府捐赠的金额逐年递减百分之十, 至第六年以后应为第一年政府编列预算 金额的百分之五十, 因此公视自筹款负担将逐年大幅增加, 对一个肩负使命的非营利电视台而言, 无疑是一个高难度的挑战。为避免过于倚赖政府捐赠, 以增加公视财务独立性,在作法上有:

    2. 企业赞助:由公、私立机构或企业团体提供经费,赞助播出之时段或节目。“企业赞助”不同于一般广告赞助,受限于电视台的基本规范,不得促销特定商品或服务、不与节目题材有任何关联或暗示、不参与任何节目制播过程等,因此能够独立自主, 避免伴随经费而来的干预。公视节目品质精緻、立意良善, 受到许多公、私立机构、企业予以肯定,并提供经费赞助, 成为公视制作精緻节目的重要支柱。

    3. 个人捐赠:成立“公视之友”会员制度,希望汇集来自民间的力量,成为公共电视在民间的重要基础。“公视之友”认同本会理念 并以捐款的方式赞助公视,公视除制作精良的节目外, 以《公视之友》月刊做为与“公视之友”沟通的桥樑,此外亦提供“公视之友”适当的回馈,如购买本会相关产品享有折扣优惠、不定期举办专题讲座等。同时, 举办文化、教育、残障等公益活动时,邀请“公视之友”担任志工, 让公共电视提倡的理念落实到生活中。

    4. 其它财源:公视拥有各类型精緻的节目为基础,利于开发各项公共电视文化事业活动,如促销与节目相关之录影带、 图书资料、教材及副产品等, 将节目资源再利用,延伸节目的制作价值。此外, 公视摄影棚、剪辑、音效等设备,在法规允许的范围内,行有馀力时, 予以出租,供其它传播公司、大学相关科系 付费使用,以合理的租金做为硬体维护费用。公视开播以来, 积极争取企业赞助,并以节目行销、 设备出租的方式获取经费; 公共电视更透过一步一脚印的 地方巡迴服务、 各项媒体的宣传及社会大众的推荐,使“公视之友”人数迅速成长,这正代表公视的理念与品质受到肯定, 成为公视往前迈进的最大动力。

    算下来,台湾人每年向公视提供 35 新台币的支持,因此每位台湾人都是公视的“干爸/干妈”

    中国台湾公共電視台
    英國公共電視台
    美國公共電視台
    日本 NHK 公共電視台
    法國公共電視台 Francetv.fr
    法國公共電視台 ARTE
    法國公共電視台 法國法蘭西 24
    加拿大公共電視台
    澳洲公共電視台
    德國公共電視台
    澳洲公共電視台(SBS)
    丹麥公共電視台
    西班牙公共電視台
    挪威公共電視台
    瑞典公共電視台
    芬蘭公共電視台

    创办历史

    公视建台历史

    1980年

    当时的行政院长孙运璿先生提出公共电视台的主张。他说,今天不做,明天会后悔。

    1983年

    新闻局提出公视节目制作中心计划草案,但因经费过高、人力庞大而搁置。

    1984年

    新闻局设立公共电视制播小组,向三家无线电视台徵用时段播出。

    1986年

    公共电视节目制作的任务,转由财团法人广电基金下设的公共电视节目制播组负责, 广电基金所制作的节目,仍然没有专属频道播出,在三台借用的时段经常被调动,影响观众收视权益。

    1991年

    行政院核定公共电视台筹备委员会设置点,公视筹委会正式运作。公视筹委会委託七位学者专家组成公共电视法草案立法小组,并经过缜密的研议,提出公共电视法草案。

    1993年

    行政院将公共电视法送交立法院审查。

    1996年9月

    一群关心公共电视的学术文化界人士 ,组成公共媒体催生联盟,结合各界支持公共电视的力量, 以促使公视法通过。

    1997年5月31日

    经由民间锲而不捨的游说及 立法院密集的政党协商, 公视法惊险过关,完成三读。

    1998年1月

    第一届公共电视董监事十八位人选经立法院推举的提名审查委员会审议通过。三月,董监事召开第一次会议,选出吴丰山先生为董事长, 贺德芬女士为常务监事。

    1998年7月1日

    财团法人公共电视文化事业基金会 正式成立,公共电视台并于同日开播,完成长达十八年的建台历程。

    公视的未来有很长的路要走, 许多困难与险阻有待我们一一克服,而您正站在公视成长的时间轴上,见证改造省内媒体环境的长期奋战, 公视盼与您携手,共同为打造媒体的美丽新“视”界努力!

    公视已在 2018 年走过了 20 个年头,而“看见更好的未来”是时代赋予它的新使命,此外公视还是全台第一家试验 4K 播出的电视台

    制播理念

    以多元的视野、多样的风貌和 高品质的专业制作来服务公众, 促进教育文化发展, 是全世界公共电视节目共同的特色, 也是公视奋力追求的目标。在节目规划上,公视秉持以下九大理念:

    1. 真心关爱儿童的成长
    2. 尊重各族群的需求
    3. 关怀弱势团体与文化
    4. 呈现表演艺术的生命力
    5. 重视台湾生态保育
    6. 纪录台湾社会变迁及人文风貌
    7. 亲近民众的生活
    8. 展现文学之美
    9. 掌握社会脉动、开拓国际视野

    公视节目不以单一节目吸引大量观众, 而是透过整体节目表的安排,由多元样貌的节目来满足不同族群, 或不同爱好者的特殊需求。为了向民众提供 有别于商业逻辑的更佳选择, 公视的节目制作涵盖下列目标:提供全民终身学习的管道。增进人民对新闻事件和公共事务的瞭解,善尽媒体监督政府的第四权责任。提供重要议题和观念的分析和解释。提供人民对台湾和他国丰富文化、 历史的认知, 并培养本土关怀和国际视野。增进国际社会对台湾风土人情的瞭解。使人民接触多元的表演艺术。提供各种社会团体如少数民族、弱势团体,公平参与的机会与表达艺术和政治上的意见空间。播映和典藏重要的影视经典作品。

    因为有《公共电视法》的庇护,公视在这些年里是有制播许多优秀节目的,这里不再一一列出,光是看“广播电视金钟奖”入围获奖名单都可以知道。

    公开透明

    这是公共媒体一个显著的特征,因为这个媒体是属于人民,服务人民的,并受到人们监督。所有相关信息,均可在官网查询到,不过仍然要遵循 CC 创用规则哦。

    频道

    公视主频是台湾的公共电视媒体——公共电视台(公视)的主频道,一般称呼为“公共电视”或简称为“公视”(部分节目预告片尾将本频道称呼为“公视频道”)。内容为综合台形式,特色是比其他无线台(台视、中视、华视、民视)更重视公共服务节目及弱势族群(儿童、老人、原住民族等)节目。中央气象局发布海上台风警报期间,公视主频道会在每整点前数分钟固定录影转播中央气象局台风动态说明会,也会在画面左侧开启滚动字幕报导台风最新动态及台风警报范围。公视的台标在节目播完后会由半透明变成“彩色”。2012 年 6 月 30 日中午起,无线电视数字化后定频于 26 频道。2016 年 6 月 8 日,NCC 通过公视换照和营运计划变更案;自 7 月 6 日起升级 HD 讯号播出,和客家电视台、原住民族电视台并列第四个主频道升级为高清讯号的电视台。2020 年 6 月 1 日,公视主频改为 24 小时全日播出,收播时间改为每月第 1 个周四 02:00~06:00。公视台语台(台湾话:Kong-sī Tâi-gí-tâi)是台湾公共电视台旗下的电视频道之一,前身为 2004 年 7 月 1 日开播的“Dimo TV”、以及 2012 年 10 月 1 日更名的“公视 2 台”,2019 年 7 月 1 日改为现名,为台湾第一个以全台语播出的公共性电视频道。公视 3 台是公共电视文化事业基金会旗下的一个电视频道,也是台湾第一个高清电视频道。由公视接受行政院新闻局“公共广电与文化创意、数字电视发展两年计划”补助建置经营。2008 年 5 月 15 日睌上 8 点起开始试播,第一个播出的节目为连续剧《美味关系》。2012 年 7 月 24 日正式开播,节目内容则以外国电影、戏曲、文化艺术和体育赛事等为主。创台之初的频道名称为“HiHD”,“Hi”是“招呼”、“迎接”之意,“HD”是“High Definition”(高清)之意。2012 年 8 月 31 日起,频道名称由“HiHD”更改为“公视 HD”。2016 年 7 月 6 日凌晨两点起更名为“公视 3 台”,定位为体育赛事、艺文、各国剧集的频道。

    Taiwan+

    为什么要把Taiwan+分离出来说,是因为TaiwanPlus开播于今年 10 月 3 日,而他的开台历程与公视有着密不可分的关系。

    Taiwan+(中文:台湾+),又称TaiwanPlus,为影音串流平台。由台湾省文化部设立、中央通讯社主责执行的“国际影音串流平台计划”,正式定名为“TaiwanPlus”,是台湾首个向国际观众宣扬台湾的英语影音新闻和节目的平台,平台于 2021 年 8 月 30 日正式上线。2022 年 6 月 9 日,平台由公共电视文化事业基金会经营,并于 10 月 3 日开播电视频道。

    中央社称,TaiwanPlus 是台湾有史以来最大的台湾视讯平台,目的是将台湾的节目、新闻和故事带到全世界,内容设定包括严肃的新闻议题、软性的文化及艺术主题。TaiwanPlus 旨在发出台湾的声音,向英语世界提供区域事件和问题的多媒体报导。 路透社则报导,TaiwanPlus 成立时,正值中国大陆积极透过英语媒界,尤其是透过中国环球电视网(CGTN),向外界传播其观点,并同时在打压台湾的国际空间。

    TaiwanPlus建台历史

    2020年7月

    台湾省文化部便开始委托公视建置英语网络影音平台,规划国际数位传播发展计划,向世界宣告台湾的经验与价值。这个名叫“国际传播数位计划”的前导计划耗资 10 亿元新台币,原计划 2021 年上线,涵盖新闻、节目、专题、纪录片等内容。外界普遍质疑该计划会令公视成为类似于我们大陆的“大外宣”机构,而公视董事冯小非曾一度于 Facebook 贴文抨击执政当局介入公视经营,罔顾公视独立性,就连公视高层也没守住应守防线。多位董事表达不满之下,公视于 7 月 27 日举行临时董事会,最终以 11 票对 4 票通过影音平台计划,时任公视总经理曹文杰、执行副总经理谢翠玉、新闻部经理苏启祯当场辞职抗议。最终,文化部于 29 日宣布终止有关“国际影音平台”委托案,但会另寻执行方式,力争次年 1 月 1 日开播。

    2021年5月

    该计划最终由中央社承接,正式定名为“TaiwanPlus”由福斯传媒集团亚洲区执行副总裁暨大中华区董事总经理蔡秋安担任执行长。

    2021年8月30日

    TaiwanPlus 影音串流平台正式上线时,也将由台湾戏剧“斯卡罗”打头阵,同步抢先在海外地区独家首播。

    2022年6月9日

    TaiwanPlus 与中央社合约到期后,由公视经营。

    2022年8月17日

    NCC 核准公视新增“TaiwanPlus”服务,以传统的电视频道形式开播,同时于其他电视平台上架,9 月 8 日起于无线数位频号 CH7 进行频道讯号测试,预计于 10 月 3 日开播。

    2022年9月14日

    中华电信 MOD 新增“TaiwanPlus”频道,于 10 月 3 日免订阅上架。定频于 558 台。

    2022年10月3日

    正式开台。

    台湾省民众最不能接受的是,参与 Taiwan Plus 平台视觉识别系统设计的 JL Design 公司,同样也接了我们的官方媒体中国中央电视台旗下中国中央电视台纪录频道中国环球电视网纪录频道的频道包装设计。2022 年 2 月,外媒驻台记者 Sam Reynolds 发现,TaiwanPlus 影音平台流量少得可怜,实在未能达到“宣扬台湾”效果。民众党对此批评,该平台无助于把台湾特色行销到世界。Taiwan Plus 软开台(Soft launch)一年后,Taiwan Plus App 下载约十二万次,相较当初设定百万人次,达成率仅一成多,引起国民党立委万美玲质疑。国民党立委林奕华郑正钤亦抨击,TaiwanPlus 的电视频道没有法源依据,“都是政府主导,要什么就要什么,没法源就要硬干”。

    我的观点

    时至今日,如果站在台湾的角度看问题,公视真的做到了它该做的吗?

    答案是确实做到了,从历年来制播表现与获奖记录,公视人为台湾电视留下了很多优秀的节目

    我记得前两年,在台语台开台的时候,对 2003 年的戏剧《后山日先照》做了修复,张美瑶确实让我为之流泪;这样的例子很多,《一把青》,《你的孩子不是你的孩子》,《我们与恶的距离》,《生死接线员》,《噬罪者》等优秀的电视剧;《公视电影院,《公视人生剧展》,《学生剧展》,《新创电影》,《听听看》,《有话好说》等一系列节目均出自公视,他会给很多新人机会,也造就了经典,“水果奶奶”应该是许多人的回忆。

    另外公视的频道包装也是很好看的,算是很有风格的 ID

    如果不被政党介入,那么也就不会有“公视门”事件?

    这个东西很难讲,我一个没参加过什么选举的人也不太好说,但有一点,公视确实会受执政党影响,而公视董事会是否能坚持住底线,又或者说公视法能不能保护公视不被外部势力侵入这个需要进一步观察。

    如果它绿了,它真的还算中立吗?

    从各个节目来看,台湾媒体一直是开放自由的状态,不论你是何种立场,均可以畅所欲言,允许不同的声音才有进步

    而你看公视新闻会与其他台会感觉有明显差异,首先英语,越南语,泰语,台语,手语等新闻的播出是一种创新的国际化尝试,新闻内容也不局限于鸡毛蒜皮的小事,主播在播报时也不太会有个人立场的介入,因此算得上中规中矩。

    大陆是否有会有全国性的公共媒体?

    我觉得不太好说,至少目前这个阶段我觉得先把节目分级制度搞定比较重要,不要一刀切,允许更多的创作自由才有更多优秀的作品。我一直相信我们大陆的电影,电视或者综艺都可以做的更好,只是目前限制条件过多受到影响较大。


    最后,希望两岸早日完成和平统一,落叶归根!

    ]]>
    台湾台湾https://blog.ccknbc.cc/posts/about-pts/#post-comment
    \ No newline at end of file diff --git a/sitemap.txt b/sitemap.txt new file mode 100644 index 000000000..f81594e88 --- /dev/null +++ b/sitemap.txt @@ -0,0 +1,52 @@ +https://blog.ccknbc.cc/manifest.json +https://blog.ccknbc.cc/about/ +https://blog.ccknbc.cc/posts/the-real-addthis/ +https://blog.ccknbc.cc/posts/hexo-webpushr-notification/ +https://blog.ccknbc.cc/privacy-policy/ +https://blog.ccknbc.cc/music/ +https://blog.ccknbc.cc/offline/ +https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/ +https://blog.ccknbc.cc/sub/ +https://blog.ccknbc.cc/moments/ +https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/ +https://blog.ccknbc.cc/posts/about-pts/ +https://blog.ccknbc.cc/posts/yuque-to-hexo/ +https://blog.ccknbc.cc/posts/how-to-hide-hexo-articles-gracefully/ +https://blog.ccknbc.cc/blogroll/ +https://blog.ccknbc.cc/essay/ +https://blog.ccknbc.cc/essay/speak/ +https://blog.ccknbc.cc/will/ +https://blog.ccknbc.cc/posts/ccs-work-diary-part3/ +https://blog.ccknbc.cc/posts/ccs-work-diary-part2/ +https://blog.ccknbc.cc/posts/2fa-last-security-line/ +https://blog.ccknbc.cc/posts/google-adsense-configuration-manual/ +https://blog.ccknbc.cc/posts/56th-golden-bell-awards/ +https://blog.ccknbc.cc/posts/waline-comments-system-deployment-logs/ +https://blog.ccknbc.cc/posts/ccs-work-diary-part1/ +https://blog.ccknbc.cc/posts/ta-said-nothing/ +https://blog.ccknbc.cc/categories/ +https://blog.ccknbc.cc/tags/ +https://blog.ccknbc.cc/posts/implementation-of-simple-browser-update-push/ +https://blog.ccknbc.cc/posts/awesome-status-pages/ +https://blog.ccknbc.cc/posts/introduction-of-plugin-tags-based-on-butterfly/ +https://blog.ccknbc.cc/posts/add-email-subscription-to-your-hexo-blog/ +https://blog.ccknbc.cc/posts/cusdis-or-disqus/ +https://blog.ccknbc.cc/posts/github-automatically-merges-pull-requests-notes/ +https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/ +https://blog.ccknbc.cc/posts/research-on-image-denoising-technology-based-on-wavelet-transform/ +https://blog.ccknbc.cc/posts/how-to-ask-questions-the-smart-way/ +https://blog.ccknbc.cc/posts/special-test-article/ +https://blog.ccknbc.cc/posts/the-webp-road-of-blog-pictures/ +https://blog.ccknbc.cc/posts/i-dont-really-want-html/ +https://blog.ccknbc.cc/posts/playlist-conversion-of-major-music-platforms/ +https://blog.ccknbc.cc/posts/how-to-enjoy-joox-music-service-in-mainland-china/ +https://blog.ccknbc.cc/posts/course-design/ +https://blog.ccknbc.cc/posts/why-github-actions-is-so-popular/ +https://blog.ccknbc.cc/posts/why-did-i-choose-tidio-as-the-chat-system/ +https://blog.ccknbc.cc/posts/about-the-55th-golden-bell-awards/ +https://blog.ccknbc.cc/posts/resume-template/ +https://blog.ccknbc.cc/posts/uptime-free-website-survival-monitoring/ +https://blog.ccknbc.cc/posts/hexo-toss/ +https://blog.ccknbc.cc/posts/production-practice/ +https://blog.ccknbc.cc/posts/digital-watermark-detection-based-on-wavelet-transform/ +https://blog.ccknbc.cc/ diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..8553b42fd --- /dev/null +++ b/sitemap.xml @@ -0,0 +1 @@ +https://blog.ccknbc.cc/manifest.json2023-07-11monthly0.6https://blog.ccknbc.cc/about/2023-07-05monthly0.6https://blog.ccknbc.cc/posts/the-real-addthis/2023-06-25monthly0.6https://blog.ccknbc.cc/posts/hexo-webpushr-notification/2023-06-25monthly0.6https://blog.ccknbc.cc/privacy-policy/2023-06-10monthly0.6https://blog.ccknbc.cc/music/2023-06-09monthly0.6https://blog.ccknbc.cc/offline/2023-05-29monthly0.6https://blog.ccknbc.cc/posts/song-about-you-live-in-the-sky-2023/2023-03-12monthly0.6https://blog.ccknbc.cc/sub/2023-02-19monthly0.6https://blog.ccknbc.cc/moments/2023-02-16monthly0.6https://blog.ccknbc.cc/posts/hexo-butterfly-algolia/2023-02-16monthly0.6https://blog.ccknbc.cc/posts/about-pts/2022-10-16monthly0.6https://blog.ccknbc.cc/posts/yuque-to-hexo/2022-10-04monthly0.6https://blog.ccknbc.cc/posts/how-to-hide-hexo-articles-gracefully/2022-09-18monthly0.6https://blog.ccknbc.cc/blogroll/2022-08-27monthly0.6https://blog.ccknbc.cc/essay/2022-08-27monthly0.6https://blog.ccknbc.cc/essay/speak/2022-08-27monthly0.6https://blog.ccknbc.cc/will/2022-06-26monthly0.6https://blog.ccknbc.cc/posts/ccs-work-diary-part3/2022-06-14monthly0.6https://blog.ccknbc.cc/posts/ccs-work-diary-part2/2021-12-02monthly0.6https://blog.ccknbc.cc/posts/2fa-last-security-line/2021-12-01monthly0.6https://blog.ccknbc.cc/posts/google-adsense-configuration-manual/2021-11-08monthly0.6https://blog.ccknbc.cc/posts/56th-golden-bell-awards/2021-10-13monthly0.6https://blog.ccknbc.cc/posts/waline-comments-system-deployment-logs/2021-09-28monthly0.6https://blog.ccknbc.cc/posts/ccs-work-diary-part1/2021-08-28monthly0.6https://blog.ccknbc.cc/posts/ta-said-nothing/2021-07-20monthly0.6https://blog.ccknbc.cc/categories/2021-07-18monthly0.6https://blog.ccknbc.cc/tags/2021-07-18monthly0.6https://blog.ccknbc.cc/posts/implementation-of-simple-browser-update-push/2021-05-18monthly0.6https://blog.ccknbc.cc/posts/awesome-status-pages/2021-05-18monthly0.6https://blog.ccknbc.cc/posts/introduction-of-plugin-tags-based-on-butterfly/2021-05-16monthly0.6https://blog.ccknbc.cc/posts/add-email-subscription-to-your-hexo-blog/2021-05-15monthly0.6https://blog.ccknbc.cc/posts/cusdis-or-disqus/2021-05-12monthly0.6https://blog.ccknbc.cc/posts/github-automatically-merges-pull-requests-notes/2021-01-17monthly0.6https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/2021-01-11monthly0.6https://blog.ccknbc.cc/posts/research-on-image-denoising-technology-based-on-wavelet-transform/2021-01-10monthly0.6https://blog.ccknbc.cc/posts/how-to-ask-questions-the-smart-way/2020-12-30monthly0.6https://blog.ccknbc.cc/posts/special-test-article/2020-12-27monthly0.6https://blog.ccknbc.cc/posts/the-webp-road-of-blog-pictures/2020-12-15monthly0.6https://blog.ccknbc.cc/posts/i-dont-really-want-html/2020-11-26monthly0.6https://blog.ccknbc.cc/posts/playlist-conversion-of-major-music-platforms/2020-11-14monthly0.6https://blog.ccknbc.cc/posts/how-to-enjoy-joox-music-service-in-mainland-china/2020-11-10monthly0.6https://blog.ccknbc.cc/posts/course-design/2020-11-03monthly0.6https://blog.ccknbc.cc/posts/why-github-actions-is-so-popular/2020-10-06monthly0.6https://blog.ccknbc.cc/posts/why-did-i-choose-tidio-as-the-chat-system/2020-10-03monthly0.6https://blog.ccknbc.cc/posts/about-the-55th-golden-bell-awards/2020-09-26monthly0.6https://blog.ccknbc.cc/posts/resume-template/2020-09-13monthly0.6https://blog.ccknbc.cc/posts/uptime-free-website-survival-monitoring/2020-08-20monthly0.6https://blog.ccknbc.cc/posts/hexo-toss/2020-07-01monthly0.6https://blog.ccknbc.cc/posts/production-practice/2020-06-29monthly0.6https://blog.ccknbc.cc/posts/digital-watermark-detection-based-on-wavelet-transform/2020-06-09monthly0.6https://blog.ccknbc.cc/2023-07-11daily1.0 \ No newline at end of file diff --git a/sub/index.html b/sub/index.html new file mode 100644 index 000000000..212486400 --- /dev/null +++ b/sub/index.html @@ -0,0 +1,19 @@ +订阅部落格文章更新 | CC的部落格

    订阅部落格文章更新

    以下方式均支持随时取消订阅,偏好可随时更改

    1. RSS订阅(全文)复制RssAtom地址通过邮件或阅读器阅读

    2. 浏览器订阅(摘要)您应该收到本站订阅弹窗通知,如果没有,您可能需要检查一下是否被广告拦截插件拦截。点击弹窗订阅按钮(可选择不同订阅主题),并确认允许本站通知后,即可在文章有更新时通过浏览器给您发送通知。建议您在 Windows 上采取此种方式,且 Edge 浏览器效果较好;由于谷歌推送服务的原因 Chrome 基本接收不到通知。即使您清除了本站浏览器数据,当您重新浏览本站时,可能也会为您自动重新订阅,除非您主动取消订阅

      点击按钮修改您的订阅配置
    3. 邮件订阅(全文)跳转后通过Follow.it订阅,注册用户支持自定义关键词、标签及多渠道(例如Telegram, Twitter,将来会支持微信)通知。

      未注册用户可在本页使用下表API订阅,但需要通过谷歌人机验证


    评论
    \ No newline at end of file diff --git a/sw.js b/sw.js new file mode 100644 index 000000000..f387a6c5f --- /dev/null +++ b/sw.js @@ -0,0 +1,145 @@ +importScripts("https://cdn1.tianli0.top/npm/workbox-sw/build/workbox-sw.js"); +importScripts("https://cdn.webpushr.com/sw-server.min.js"); + +if (workbox) { + console.log("Workbox 加载成功🎉"); +} else { + console.log("Workbox 加载失败😬"); +} + +workbox.precaching.cleanupOutdatedCaches(); + +self.addEventListener("install", async () => { + await self.skipWaiting(); + console.log("Service Worker 开始安装🎊"); +}); + +self.addEventListener("activate", async () => { + await self.clients.claim(); + console.log("Service Worker 安装完成,开始启动✨"); + self.clients.matchAll().then((clients) => { + clients.forEach((client) => client.postMessage({ type: "refresh" })); + }); +}); + +self.__WB_DISABLE_DEV_LOGS = true; + +self.addEventListener('fetch', event => { + const url = new URL(event.request.url) + const domain = url.hostname + if (domain === 'cdn.nlark.com' || domain === 'pic1.afdiancdn.com' || domain === 'f.video.weibocdn.com' || domain === 'api.icodeq.com') { + event.respondWith( + fetch(event.request, { + referrerPolicy: "no-referrer" + }) + ) + } +}); + +workbox.core.setCacheNameDetails({ + prefix: "CC的部落格", + suffix: "缓存", + precache: "预先", + runtime: "运行时", + googleAnalytics: "离线谷歌分析", +}); + +workbox.precaching.precacheAndRoute([{"revision":"78004bb3842edcc19c7c6fcf51ccd09b","url":"./css/custom.css"},{"revision":"004a9ab42f5579703a2b8225fccac51c","url":"./css/index.css"},{"revision":"d41d8cd98f00b204e9800998ecf8427e","url":"./css/var.css"},{"revision":"c5c534d0ec6fcf9b9e84f3bbf97bf6b7","url":"./js/custom.js"},{"revision":"eb9c0d5f97e38137fdfd98308816b909","url":"./js/main.js"},{"revision":"a603233b64d8f839af4f53cc1ef5706a","url":"./js/tw_cn.js"},{"revision":"4ac6ab73b303661bc180cc769d0caca4","url":"./js/utils.js"},{"revision":"0e8f6d50614f6143f25526e60216c781","url":"./offline/index.html"}], { + ignoreUrlParametersMatching: [/.*/], + directoryIndex: null, +}); + +const MIN = 60; +const HOUR = MIN * 60; +const DAY = HOUR * 24; +const WEEK = DAY * 7; +const MONTH = DAY * 30; +const YEAR = DAY * 365; + +// 导航预加载 +workbox.navigationPreload.enable(); + +// 离线后备 +const Offline = new workbox.routing.Route( + ({ request }) => { + return request.mode === "navigate"; + }, + new workbox.strategies.NetworkOnly({ + plugins: [ + new workbox.precaching.PrecacheFallbackPlugin({ + fallbackURL: "/offline/index.html", + }), + new workbox.cacheableResponse.CacheableResponsePlugin({ + statuses: [0, 200], + }), + ], + }) +); +workbox.routing.registerRoute(Offline); + +workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly()); + +// 暖策略(运行时)缓存 +const strategy = new workbox.strategies.StaleWhileRevalidate(); +const urls = [ + '/favicon.ico' +]; +workbox.recipes.warmStrategyCache({ urls, strategy }); + +// 字体 +workbox.routing.registerRoute( + ({ event }) => event.request.destination === 'font', + new workbox.strategies.StaleWhileRevalidate({ + cacheName: "字体", + plugins: [ + new workbox.expiration.ExpirationPlugin({ + maxEntries: 10, + maxAgeSeconds: MONTH, + }), + new workbox.cacheableResponse.CacheableResponsePlugin({ + statuses: [0, 200], + }), + ], + }) +); + +// json +workbox.routing.registerRoute( + ({ request }) => request.url.endsWith('.json'), + new workbox.strategies.NetworkFirst({ + cacheName: "网络资源", + plugins: [ + new workbox.expiration.ExpirationPlugin({ + maxEntries: 10, + maxAgeSeconds: DAY, + }), + new workbox.cacheableResponse.CacheableResponsePlugin({ + statuses: [0, 200], + }), + ], + }) +); + +// busuanzi +workbox.routing.registerRoute( + ({ url }) => String(url).includes('busuanzi?') || String(url).includes('busuanzi='), + new workbox.strategies.NetworkOnly() +); + +// 静态资源 +workbox.routing.registerRoute( + new RegExp(".*.(?:css|js)"), + new workbox.strategies.StaleWhileRevalidate({ + cacheName: "静态资源", + plugins: [ + new workbox.expiration.ExpirationPlugin({ + maxEntries: 50, + maxAgeSeconds: WEEK, + }), + new workbox.cacheableResponse.CacheableResponsePlugin({ + statuses: [0, 200], + }), + ], + }) +); + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 000000000..7a3b52f70 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,19 @@ +文章标签 | CC的部落格
    \ No newline at end of file diff --git "a/tags/\345\215\232\345\256\242/index.html" "b/tags/\345\215\232\345\256\242/index.html" new file mode 100644 index 000000000..3abb40b68 --- /dev/null +++ "b/tags/\345\215\232\345\256\242/index.html" @@ -0,0 +1,19 @@ +标签: 博客 | CC的部落格
    \ No newline at end of file diff --git "a/tags/\345\217\260\346\271\276/index.html" "b/tags/\345\217\260\346\271\276/index.html" new file mode 100644 index 000000000..cc70cea97 --- /dev/null +++ "b/tags/\345\217\260\346\271\276/index.html" @@ -0,0 +1,19 @@ +标签: 台湾 | CC的部落格
    标签 - 台湾
    2023
    2023《好好》线上演唱会
    2023《好好》线上演唱会
    2022
    你的公共电视
    你的公共电视
    2021
    第56届电视金钟奖
    第56届电视金钟奖
    2020
    第55届金钟奖相关
    第55届金钟奖相关
    \ No newline at end of file diff --git "a/tags/\345\255\246\344\271\240/index.html" "b/tags/\345\255\246\344\271\240/index.html" new file mode 100644 index 000000000..575f3de9e --- /dev/null +++ "b/tags/\345\255\246\344\271\240/index.html" @@ -0,0 +1,19 @@ +标签: 学习 | CC的部落格
    \ No newline at end of file diff --git "a/tags/\345\267\245\344\275\234/index.html" "b/tags/\345\267\245\344\275\234/index.html" new file mode 100644 index 000000000..56c6a941b --- /dev/null +++ "b/tags/\345\267\245\344\275\234/index.html" @@ -0,0 +1,19 @@ +标签: 工作 | CC的部落格
    标签 - 工作
    2022
    CC的社畜日记 Part3
    CC的社畜日记 Part3
    2021
    CC的社畜日记 Part2
    CC的社畜日记 Part2
    CC的社畜日记 Part1
    CC的社畜日记 Part1
    2020
    简历模板
    简历模板
    \ No newline at end of file diff --git "a/tags/\345\267\245\345\205\267/index.html" "b/tags/\345\267\245\345\205\267/index.html" new file mode 100644 index 000000000..b7a9aa179 --- /dev/null +++ "b/tags/\345\267\245\345\205\267/index.html" @@ -0,0 +1,19 @@ +标签: 工具 | CC的部落格
    \ No newline at end of file diff --git "a/tags/\347\224\237\346\264\273/index.html" "b/tags/\347\224\237\346\264\273/index.html" new file mode 100644 index 000000000..95c5ca64f --- /dev/null +++ "b/tags/\347\224\237\346\264\273/index.html" @@ -0,0 +1,19 @@ +标签: 生活 | CC的部落格
    标签 - 生活
    2021
    Ta 什么都不说
    Ta 什么都不说
    \ No newline at end of file diff --git "a/tags/\351\237\263\344\271\220/index.html" "b/tags/\351\237\263\344\271\220/index.html" new file mode 100644 index 000000000..a29db4b3f --- /dev/null +++ "b/tags/\351\237\263\344\271\220/index.html" @@ -0,0 +1,19 @@ +标签: 音乐 | CC的部落格
    \ No newline at end of file diff --git a/will/index.html b/will/index.html new file mode 100644 index 000000000..b7abbfd21 --- /dev/null +++ b/will/index.html @@ -0,0 +1,19 @@ +遗嘱(起草版) | CC的部落格

    遗嘱(起草版)

    简体中文版

    我孙泽康自立遗书如下
    1. 如果我本人超过60足岁,而且一年以上无法进食,自理便溺,可将本人送至具医院背景的养护中心,费用由本人负担

    2. 不气切,不电击,不要腹部灌食,不要积极救治

    3. 不择时日,不印讣文,不设灵堂,不收白包奠仪,一切从简,尽速火化

    4. 剩下的遗产,在我死后全数捐给慈善机构,帮助没有儿女照顾的独居老人

    5. 若被判定为脑死,请器官捐赠协调师尽力説服家属,包括遗体在内的可用器官捐赠

    6. 因本人可能身边无亲属,不具法律效益,但希望尽可能能按照遗嘱置办

    English version

    I, Sun Zekang, make my own will and testament as follows
    1. If I am over 60 years old and unable to eat or manage my own bowels for more than one year, I may be sent to a care center with a hospital background at my expense.

    2. no pneumonectomy, no electroshock, no abdominal irrigation, no active treatment.

    3. no date, no obituary, no funeral hall, no white bag, all simple, cremation as soon as possible.

    4. donate the rest of my estate to charity after my death to help the elderly who live alone without children.

    5. If I am judged to be brain dead, I will ask my organ donor coordinator to help my family to donate all available organs, including my body.

    6. Since I may not have any relatives around, I will not be legally entitled to do so, but I hope that I can do as much as possible in accordance with my will.

    繁體中文版

    我孫澤康自立遺書如下
    1. 如果我本人超過60足歲,而且一年以上無法進食,自理便溺,可將本人送至具醫院背景的養護中心,費用由本人負擔

    2. 不氣切,不電擊,不要腹部灌食,不要積極救治

    3. 不擇時日,不印訃文,不設靈堂,不收白包奠儀,一切從簡,儘速火化

    4. 剩下的遺產,在我死後全數捐給慈善機構,幫助沒有兒女照顧的獨居老人

    5. 若被判定為腦死,請器官捐贈協調師盡力説服家屬,包括遺體在内的可用器官捐贈

    6. 因本人可能身邊無親屬,不具法律效益,但希望盡可能能按照遺囑置辦


    评论

    扫一扫

    快速打开移动端➤
    扫一扫二维码 快速打开移动端

    扫一扫

    请我喝杯牛奶➤
    扫一扫二维码 请我喝杯牛奶
    \ No newline at end of file