Browse Source

仓库初始化

master
453530270@qq.com 3 years ago
commit
c78b3f46a6
  1. 17
      .editorconfig
  2. 45
      .eslintignore
  3. 11
      .gitignore
  4. 202
      LICENSE
  5. 89
      README.md
  6. 86
      README_en-US.md
  7. 17
      babel.config.js
  8. 93
      build/build.js
  9. 85
      build/build.plugin.js
  10. 77
      build/build.qa.js
  11. 18
      build/fixInnerHTML.js
  12. 167
      build/manifest.js
  13. 30
      build/postcssSplitMediaPlugin.js
  14. 107
      build/rollup.config.app.js
  15. 106
      build/rollup.config.mp.js
  16. 94
      build/rollup.config.qa.js
  17. 38
      build/rollup.config.service.js
  18. 20
      build/rollup.config.stat.js
  19. 25
      build/rollup.config.web-view.js
  20. 7
      build/rollup.config.wxs.js
  21. 69
      build/vue.config.js
  22. 80
      build/webpack.config.js
  23. 58
      build/webpack.config.test.js
  24. 21
      check-version.js
  25. 17
      dist-tag-latest.js
  26. 1
      dist/uni.webview.1.5.2.js
  27. 1
      dist/uni.webview.1.5.3.js
  28. 1
      dist/uni.webview.1.5.4.js
  29. 1
      dist/uni.webview.1.5.5.js
  30. 2
      docs/README.md
  31. 1
      examples/hello-uniapp/README.md
  32. 1
      examples/image-template/README.md
  33. 1
      examples/login-template/README.md
  34. 75
      examples/uniapp-one/App.vue
  35. 11
      examples/uniapp-one/README.md
  36. 64
      examples/uniapp-one/components/article.vue
  37. 89
      examples/uniapp-one/components/movieItem.vue
  38. 97
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseImg.vue
  39. 101
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate0.vue
  40. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate1.vue
  41. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate10.vue
  42. 80
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate11.vue
  43. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate2.vue
  44. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate3.vue
  45. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate4.vue
  46. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate5.vue
  47. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate6.vue
  48. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate7.vue
  49. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate8.vue
  50. 92
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate9.vue
  51. 15
      examples/uniapp-one/components/mpvue-wxparse/components/wxParseVideo.vue
  52. 252
      examples/uniapp-one/components/mpvue-wxparse/libs/html2json.js
  53. 188
      examples/uniapp-one/components/mpvue-wxparse/libs/htmlparser.js
  54. 197
      examples/uniapp-one/components/mpvue-wxparse/libs/wxDiscode.js
  55. 257
      examples/uniapp-one/components/mpvue-wxparse/wxParse.css
  56. 65
      examples/uniapp-one/components/mpvue-wxparse/wxParse.vue
  57. 97
      examples/uniapp-one/components/questionList.vue
  58. 98
      examples/uniapp-one/components/readList.vue
  59. 13
      examples/uniapp-one/main.js
  60. 53
      examples/uniapp-one/manifest.json
  61. 79
      examples/uniapp-one/pages.json
  62. 145
      examples/uniapp-one/pages/daily/detail/main.vue
  63. 141
      examples/uniapp-one/pages/daily/main.vue
  64. 65
      examples/uniapp-one/pages/home/main.vue
  65. 56
      examples/uniapp-one/pages/home/weather.vue
  66. 38
      examples/uniapp-one/pages/movie/detail/main.vue
  67. 51
      examples/uniapp-one/pages/movie/main.vue
  68. 34
      examples/uniapp-one/pages/read/essay/main.vue
  69. 68
      examples/uniapp-one/pages/read/main.vue
  70. 92
      examples/uniapp-one/pages/read/question/main.vue
  71. BIN
      examples/uniapp-one/static/assert/arrow-right.png
  72. BIN
      examples/uniapp-one/static/assert/music.png
  73. BIN
      examples/uniapp-one/static/assert/pause.png
  74. BIN
      examples/uniapp-one/static/assert/play.png
  75. BIN
      examples/uniapp-one/static/icon/daily-active.png
  76. BIN
      examples/uniapp-one/static/icon/daily.png
  77. BIN
      examples/uniapp-one/static/icon/home-active.png
  78. BIN
      examples/uniapp-one/static/icon/home.png
  79. BIN
      examples/uniapp-one/static/icon/movie-active.png
  80. BIN
      examples/uniapp-one/static/icon/movie.png
  81. BIN
      examples/uniapp-one/static/icon/read-active.png
  82. BIN
      examples/uniapp-one/static/icon/read.png
  83. 33
      examples/uniapp-one/store/index.js
  84. 38
      examples/uniapp-one/store/modules/home.js
  85. 40
      examples/uniapp-one/store/modules/movie.js
  86. 47
      examples/uniapp-one/store/modules/read.js
  87. 38
      examples/uniapp-one/store/modules/weather.js
  88. 14
      examples/uniapp-one/store/mutations_type.js
  89. 29
      examples/uniapp-one/utils/api.js
  90. 29
      examples/uniapp-one/utils/request.js
  91. 25
      examples/wxcomponents-template/App.vue
  92. 12
      examples/wxcomponents-template/README.md
  93. 11
      examples/wxcomponents-template/main.js
  94. 55
      examples/wxcomponents-template/manifest.json
  95. 37
      examples/wxcomponents-template/pages.json
  96. 22
      examples/wxcomponents-template/pages/index/index.vue
  97. 32
      examples/wxcomponents-template/pages/vant/vant.vue
  98. 80
      examples/wxcomponents-template/pages/wux/wux.vue
  99. 0
      examples/wxcomponents-template/static/.gitkeep
  100. 29
      examples/wxcomponents-template/wxcomponents/vant-weapp/dist/common/class-names.js

17
.editorconfig

@ -0,0 +1,17 @@
# http://editorconfig.org
root = true
# all files
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = crlf
insert_final_newline = true
trim_trailing_whitespace = true
# md files
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

45
.eslintignore

@ -0,0 +1,45 @@
src/core/helpers/html-parser.js
src/platforms/app-plus-nvue/runtime
src/platforms/app-plus/service/api/plugin/uts.js
build/rollup-plugin-require-context
packages/*/packages/uni-app-plus
packages/*/packages/uni-app-plus-nvue
packages/*/packages/uni-app-plus-nvue-v8
packages/*/packages/weex-styler
packages/*/packages/weex-template-compiler
packages/*/packages/@intervolga
packages/*/packages/@megalo
packages/*/packages/@vue
packages/*/packages/app-vue-style-loader
packages/*/packages/h5-vue
packages/*/packages/h5-vue-router
packages/*/packages/h5-vue-style-loader
packages/*/packages/megalo
packages/*/packages/mp-vue
packages/*/packages/mpvue
packages/*/packages/mpvue-page-factory
packages/*/packages/mpvue-template-compiler
packages/*/packages/postcss-normalize-whitespace
packages/*/packages/uni-app
packages/*/packages/uni-push
packages/*/packages/uni-stat
packages/*/packages/uni-cloud
packages/*/packages/vue-loader
packages/*/packages/vue-template-compiler
packages/*/packages/webpack-preprocess-loader/preprocess
packages/*/packages/sass-loader
packages/*/packages/vuex
packages/*/packages/vuex3
packages/*/template/**/*
packages/uni-h5/src
packages/uni-stat
node_modules
automator.js
uni.automator.js
uni-polyfill.js
packages/uni-cli-shared/components/ad-fullscreen-video.vue
packages/uni-cli-shared/components/ad-interactive.vue
packages/uni-cli-shared/components/ad-interstitial.vue
packages/uni-cli-shared/components/ad-rewarded-video.vue
packages/uni-cli-shared/lib/uni_modules/uni_modules.js
packages/uni-cli-shared/lib/uts/uts.js

11
.gitignore

@ -0,0 +1,11 @@
node_modules/
.project
unpackage/
.vscode/
.idea
.DS_Store
!packages/uni-app-plus/dist
package-lock.json
!packages/vue-cli-plugin-uni/packages/**/*
tests/package.json
*.DS_Store

202
LICENSE

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

89
README.md

@ -0,0 +1,89 @@
# uni-app
<p>
简体中文 | <a href="https://github.com/dcloudio/uni-app/blob/dev/README_en-US.md">English</a>
</p>
`uni-app` 是一个使用 `Vue.js` 开发小程序、H5、App的统一前端框架。官网地址:[https://uniapp.dcloud.io](https://uniapp.dcloud.io)
开发者使用 `Vue` 语法编写代码,`uni-app` 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/快手/钉钉/小红书)、App(iOS/Android)、H5等多个平台,保证其正确运行并达到优秀体验。
# uni-app的特点
- 开发者和案例更多:HBuilder装机量800万台,开发者社区月活百万,70多个QQ微信群承载10万人。案例众多,uni统计月活超10亿([详见](https://uniapp.dcloud.io/case))
- 性能更高(见[评测](https://juejin.im/post/5ca1736af265da30ae314248))
- 更丰富的周边生态,[插件市场](https://ext.dcloud.net.cn/)数千款插件
- 提供比小程序原生开发更好的开发体验、更高的工程化效率
- 跨端抹平度更完善,且各端特色发挥更灵活,可真正实现一套代码多端覆盖,无需各端多头维护升级
- 权威认可:阿里小程序官方工具内置uni-app([详见](https://docs.alipay.com/mini/ide/0.70-stable))、腾讯课堂官方自制uni-app培训视频([详见](https://ask.dcloud.net.cn/article/35640))
## 扫码体验
开发一次,编译到14个平台。依次扫描14个二维码,亲自体验最全面的跨平台效果!
<div align="center">
<img src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-a90b5f95-90ba-4d30-a6a7-cd4d057327db/cf5727bc-fbe6-4d7e-bd92-e0d16e6f53b0.jpg"/>
</div>
*注: 某些平台不能提交简单demo,补充了一些其他功能。*
## 快速开始
`uni-app`支持通过`vue-cli`命令行、`HBuilderX`可视化界面两种方式快速创建项目:
- [vue-cli命令行方式](https://uniapp.dcloud.io/quickstart?id=_2-通过vue-cli命令行):不限IDE,适合对node熟悉的开发者,扩展阅读:[在vscode中开发uni-app](https://ask.dcloud.net.cn/article/36286)、[在 WebStorm 中开发 uni-app](https://ask.dcloud.net.cn/article/36307)
- [HBuilderX可视化界面](https://uniapp.dcloud.io/quickstart?id=_1-通过-hbuilderx-可视化界面):专用IDE,内置相关环境,开箱即用,开发效率更高。
## 项目案例
案例展示:[uniapp.dcloud.io/case](https://uniapp.dcloud.io/case)
欢迎提交你的应用,[uni-app案例征集](https://github.com/dcloudio/uni-app/issues/6)
## 需求墙
`uni-app`计划支持的功能点,会在需求墙上进行展示,征集开发者的投票意见,[前往投票](https://dev.dcloud.net.cn/wish/)。
## 更新日志
`uni-app`一直保持高频的更新迭代,详见[正式版更新日志](https://uniapp.dcloud.net.cn/release)、[Alpha版更新日志](https://uniapp.dcloud.net.cn/release-note-alpha)。
## 论坛
由于`DCloud`有70多个QQ、微信群,官方已无法维护更多交流群。请开发者到官方论坛交流:[https://ask.dcloud.net.cn/explore/](https://ask.dcloud.net.cn/explore/) 。论坛提供了比issues更专业的工具服务。
## 插件市场
`uni-app`有丰富的插件生态,众多开发者提交了数千款组件、sdk、项目模板,详见:[https://ext.dcloud.net.cn/](https://ext.dcloud.net.cn/)
除了众多三方ui库,官方还提供了uni-ui,在性能和跨端兼容方面有更强的优势。详见:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
## 现有项目如何迁移到uni-app体系
- 微信小程序转换uni-app指南及转换器:[https://ask.dcloud.net.cn/article/35786](https://ask.dcloud.net.cn/article/35786)
- vue h5项目转换uni-app指南:[https://ask.dcloud.net.cn/article/36174](https://ask.dcloud.net.cn/article/36174)
- mpvue 项目(组件)迁移指南、示例及资源汇总: [https://ask.dcloud.net.cn/article/34945](https://ask.dcloud.net.cn/article/34945)
- wepy转uni-app转换器:[https://github.com/zhangdaren/wepy-to-uniapp](https://github.com/zhangdaren/wepy-to-uniapp)
## 常见疑问
- 问:不同端有不同的需求、不同的特色,登录支付也不一样,如何统一?
- 答:差异部分使用条件编译。uni-app提供了灵活强大的[条件编译](https://uniapp.dcloud.io/platform)。可以完美处理复用部分和差异部分。真正一套工程源码。当业务升级时,不再需要多端维护。如果多端维护,经常会因为某些端的流量不大,就一直拖延无法让那些用户享受到最新服务。另外登录支付在客户端部分,已经被uni-app统一成一样的api了。
- 问:多端是不是一种妥协,是否会造成性能下降?
- 答:good question。多端且不影响性能,确实很难,但uni-app做到了。在h5端,它的性能、包体积与直接使用vue.js开发一致; 在小程序端,它的性能比大多数开发框架更好,uni-app底层自动处理的setdata差量同步机制,比开发者手动写setdata更好,就像使用vue.js更新界面比手动写js修改dom更高效一样; 在App,uni-app支持webview渲染和原生渲染双引擎,启用原生渲染时,css写法受限,但性能是很接近原生开发的效果的,在当前的手机环境下,千万日活以下的应用在App使用uni-app也不会遇到任何压力。当然也可以在已经做好的原生App中将部分页面改为uni-app实现; 此外,我们会把很多跨端处理放在编译期完成的,这样会减少对运行期的效率影响。
- 问:不做多端,是不是不需要uni-app?
- 答:不是。大量开发者用uni-app只做一个端,详见[案例](https://uniapp.dcloud.io/case)。对于开发者而言,一个优秀工具在手,做什么都不愁。
- 问:uni-app以后会不会变更开源协议,转向收费?
- 答:官方承诺永远不会变更开源协议。无论HBuilderX、uni-app、App,面向中国人永久免费。
## 更多资料
- 评测:[跨端开发框架深度横评之2020版](https://juejin.im/post/5e8e8d5a6fb9a03c6d3d9f42)
- 评测:[深入测试一周,主流多端框架大比武](https://mp.weixin.qq.com/s/jIDEHfuMnED6HTfNgjsW4w)
- [uni-app在App端和flutter、react native的比较](https://ask.dcloud.net.cn/article/36083)

86
README_en-US.md

@ -0,0 +1,86 @@
# uni-app
<p>
<a href="https://github.com/dcloudio/uni-app/blob/dev/README.md">简体中文</a> | English
</p>
`uni-app` is a unified front-end framework that uses `Vue.js` to develop applet, H5, and App. Official website address: [https://uniapp.dcloud.io](https://uniapp.dcloud.io)
Developers use `Vue` syntax to write code, and `uni-app` framework compiles it into small programs (WeChat/Alipay/Baidu/ByteDance/QQ/Kuishou/Dingding/Xiaohongshu), App (iOS/Android) ), H5 and other platforms to ensure its correct operation and achieve an excellent experience.
# Features of uni-app
- More developers and cases: HBuilder has installed 8 million units, the developer community has one million monthly active users, and more than 70 QQ and WeChat groups carry 100,000 people. There are many cases, and the uni statistics exceed 1 billion monthly active users ([see details](https://uniapp.dcloud.io/case))
- Higher performance (see [Review](https://juejin.im/post/5ca1736af265da30ae314248))
- Richer surrounding ecology, [Plugin Market](https://ext.dcloud.net.cn/) thousands of plugins
- Provide a better development experience and higher engineering efficiency than the native development of small programs
- The smoothness across the ends is more complete, and the characteristics of each end are more flexible, which can truly achieve multi-end coverage of a set of codes, without the need for multi-end maintenance and upgrades at each end
- Authoritative recognition: Alipay's official tool has built-in uni-app ([see details](https://docs.alipay.com/mini/ide/0.70-stable)), Tencent Classroom's official self-made uni-app training video ([ For details, see](https://ask.dcloud.net.cn/article/35640))
## Scan code experience
Develop once, compile to 3 platforms. Scan 3 QR codes in sequence to experience the most comprehensive cross-platform effect for yourself!
<div align="center">
<img src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/3cca21df-a9af-48f8-b808-0b795acb2580.jpg"/>
</div>
## quick start
`uni-app` supports two ways to quickly create projects through the `vue-cli` command line and the `HBuilderX` visual interface:
- [vue-cli command line mode](https://uniapp.dcloud.io/quickstart?id=_2-%E9%80%9A%E8%BF%87vue-cli%E5%91%BD%E4%BB%A4%E8%A1%8C): not limited to IDE, suitable for developers familiar with node, extended reading: [Developing uni-app in vscode](https://ask.dcloud.net.cn/article/36286 ), [Developing uni-app in WebStorm](https://ask.dcloud.net.cn/article/36307)
- [HBuilderX visual interface](https://uniapp.dcloud.io/quickstart?id=_1-%E9%80%9A%E8%BF%87-hbuilderx-%E5%8F%AF%E8%A7%86%E5%8C%96%E7%95%8C%E9%9D%A2): dedicated IDE, built-in related environment, out-of-the-box, and higher development efficiency.
## Project cases
Case show: [uniapp.dcloud.io/case](https://uniapp.dcloud.io/case)
Welcome to submit your application, [uni-app case collection](https://github.com/dcloudio/uni-app/issues/6)
## Demand Wall
The function points supported by the `uni-app` plan will be displayed on the demand wall, and the voting opinions of developers will be collected. [Go to Vote](https://dev.dcloud.net.cn/wish/).
## Changelog
`uni-app` has always maintained high-frequency update iterations. For details, see [Official version update log](https://uniapp.dcloud.net.cn/release), [Alpha version update log](https://uniapp. dcloud.net.cn/release-note-alpha).
## Forum
Since `DCloud` has more than 70 QQ and WeChat groups, the official has been unable to maintain more communication groups. Please go to the official forum to communicate: [https://ask.dcloud.net.cn/explore/](https://ask.dcloud.net.cn/explore/). Forums provide more professional tools and services than issues.
## Plugin Market
`uni-app` has a rich plugin ecosystem. Many developers have submitted thousands of components, sdk, and project templates. For details, see: [https://ext.dcloud.net.cn/](https://ext.dcloud.net.cn/)
In addition to many third-party ui libraries, the official also provides uni-ui, which has stronger advantages in performance and cross-end compatibility. For details, see: [https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
## How to migrate existing projects to uni-app system
- WeChat applet conversion uni-app guide and converter: [https://ask.dcloud.net.cn/article/35786](https://ask.dcloud.net.cn/article/35786)
- Vue h5 project conversion uni-app guide: [https://ask.dcloud.net.cn/article/36174](https://ask.dcloud.net.cn/article/36174)
- mpvue project (component) migration guide, example and resource summary: [https://ask.dcloud.net.cn/article/34945](https://ask.dcloud.net.cn/article/34945)
- wepy to uni-app converter: [https://github.com/zhangdaren/wepy-to-uniapp](https://github.com/zhangdaren/wepy-to-uniapp)
## Frequently Asked Questions
- Q: Different terminals have different needs and features, and login and payment are also different. How to unify?
- A: The difference part uses conditional compilation. uni-app provides flexible and powerful [conditional compilation](https://uniapp.dcloud.io/platform). Can perfectly handle the multiplexed part and the difference part. A real set of project source code. When the business is upgraded, multi-terminal maintenance is no longer required. If there is multi-end maintenance, it is often delayed because the traffic on some ends is not large, so that those users cannot enjoy the latest services. In addition, the login payment in the client part has been unified into the same api by uni-app.
- Q: Is multi-terminal a compromise and will it cause performance degradation?
- A: good question. It's really hard to be multi-terminal without compromising performance, but uni-app does it. On the h5 side, its performance and package size are consistent with those developed directly using vue.js; on the applet side, its performance is better than most development frameworks. It is better for the user to manually write setdata, just as it is more efficient to use vue.js to update the interface than to manually write js to modify the dom; in App, uni-app supports dual engines for webview rendering and native rendering. When native rendering is enabled, css writing is limited, However, the performance is very close to the effect of native development. In the current mobile phone environment, applications with less than ten million daily activities will not encounter any pressure when using uni-app in the App. Of course, it is also possible to change some pages to uni-app in the native app that has already been done; in addition, we will complete a lot of cross-end processing at the compile time, which will reduce the efficiency impact on the runtime.
- Q: Do you not need uni-app if you don't do multi-end?
- A: No. A large number of developers use uni-app as only one end, see [Case](https://uniapp.dcloud.io/case) for details. For developers, with an excellent tool in hand, there is nothing to worry about.
- Q: Will uni-app change the open source protocol and switch to charging in the future?
- A: The official promise will never change the open source agreement. Regardless of HBuilderX, uni-app, or App, it is always free for Chinese people.
## more info
- Evaluation: [Cross-end Development Framework Deep Heng Evaluation 2020 Edition](https://juejin.im/post/5e8e8d5a6fb9a03c6d3d9f42)
- Evaluation: [In-depth testing for a week, mainstream multi-terminal frameworks compete](https://mp.weixin.qq.com/s/jIDEHfuMnED6HTfNgjsW4w)
- [Comparison of uni-app on the App side with flutter and react native](https://ask.dcloud.net.cn/article/36083)

17
babel.config.js

@ -0,0 +1,17 @@
const config = {
// ignore: [
// "./packages",
// ],
presets: [
["@vue/cli-plugin-babel/preset", {
useBuiltIns: "entry"
}]
],
plugins: [require('./lib/babel-plugin-uni-api/index.js')]
}
if (process.env.NODE_ENV === 'test') {
delete config.ignore
}
module.exports = config

93
build/build.js

@ -0,0 +1,93 @@
const {
error
} = require('@vue/cli-shared-utils')
const Service = require('@vue/cli-service')
const del = require('del')
const copy = require('copy')
const path = require('path')
const jsonfile = require('jsonfile')
const {
generateApiManifest
} = require('./manifest')
const fixInnerHTML = require('./fixInnerHTML')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd(), {
inlineOptions: require('./vue.config.js')
})
// 删除 cache 目录
del.sync(['node_modules/.cache'])
let name = 'index'
let filename = ''
let entry = './lib/' + process.env.UNI_PLATFORM + '/main.js'
if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_UI === 'true') {
entry = './lib/' + process.env.UNI_PLATFORM + '/ui.js'
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true') {
name = 'uni'
filename = 'view'
entry = './lib/' + process.env.UNI_PLATFORM + '/view.js'
}
service.run('build', {
name,
filename,
watch: process.env.UNI_WATCH === 'true',
target: 'lib',
formats: process.env.UNI_WATCH === 'true' ? 'umd' : 'umd-min',
entry,
'inline-vue': !!process.env.UNI_VIEW,
clean: false, //! process.env.UNI_VIEW,
mode: process.env.NODE_ENV
}).then(function () {
if (
process.env.UNI_WATCH !== 'true' &&
process.env.UNI_UI !== 'true' &&
process.env.UNI_VIEW !== 'true'
) {
generateApiManifest(
JSON.parse(JSON.stringify(process.UNI_SERVICE_API_MANIFEST)),
JSON.parse(JSON.stringify(process.UNI_SERVICE_API_PROTOCOL))
)
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true' && process.env.UNI_WATCH !== 'true') {
fixInnerHTML()
}
}).catch(err => {
error(err)
process.exit(1)
})
if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_WATCH === 'false') {
const packagePath = path.join(__dirname, `../packages/uni-${process.env.UNI_PLATFORM}`)
const packageJsonPath = path.join(packagePath, 'package.json')
del(path.join(packagePath, '{lib,src}'))
.then(() => {
copy([path.join(__dirname, '../{lib,src}/**/*')], packagePath, function (err, file) {
if (err) {
throw err
}
})
})
jsonfile.readFile(path.join(__dirname, '../package.json'))
.then(origin => {
return jsonfile.readFile(packageJsonPath)
.then(obj => {
obj.dependencies = origin.dependencies
return obj
})
})
.then(obj => {
return jsonfile.writeFile(packageJsonPath, obj, {
spaces: 2
})
})
.catch(err => {
throw err
})
}

85
build/build.plugin.js

@ -0,0 +1,85 @@
const path = require('path')
const del = require('del')
const {
error
} = require('@vue/cli-shared-utils')
const Service = require('@vue/cli-service')
const vueConfig = require('./vue.config.js')
const extendsApiPath = path.resolve(__dirname, '../lib/h5/extends-api')
vueConfig.configureWebpack.resolve.alias['uni-invoke-api'] = extendsApiPath
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd(), {
inlineOptions: vueConfig
})
// 删除 cache 目录
del.sync(['node_modules/.cache'])
let pluginDir = process.argv[2]
if (!pluginDir) {
console.error('缺少参数')
process.exit(0)
}
if (pluginDir.indexOf('/') === -1) {
pluginDir = path.resolve(__dirname, '../packages/uni-' + pluginDir)
}
const pkg = require(path.join(pluginDir, 'package.json'))
if (!pkg['uni-app']) {
console.error('缺少 uni-app 配置')
process.exit(0)
}
service.webpackRawConfigFns.push(function () {
return {
resolve: {
alias: {
'uni-platform/service/api.js': extendsApiPath,
'uni-sub-platform': path.resolve(pluginDir, 'src'),
'uni-platform-api': path.resolve(__dirname, '../src/platforms/h5/service/api'),
'uni-sub-platform-api': path.resolve(pluginDir, 'src/service/api')
}
},
module: {
rules: [{
test: path.resolve(__dirname, '../src/core/view/components/index.js'),
use: [{
loader: path.resolve(__dirname, '../lib/extends-component-loader'),
options: {
extends: path.resolve(pluginDir, 'src/view/components'),
base: path.resolve(__dirname, '../src/core/view/components'),
platform: path.resolve(__dirname, '../src/platforms/h5/view/components')
}
}]
}, {
test: path.resolve(__dirname, '../src/platforms/h5/service/api/index.js'),
use: [{
loader: path.resolve(__dirname, '../lib/extends-api-loader'),
options: {
extends: path.resolve(pluginDir, 'src/service/api'),
base: path.resolve(__dirname, '../src/platforms/h5/service/api')
}
}]
}]
}
}
})
service.run('build', {
name: 'index',
watch: process.env.UNI_WATCH === 'true',
target: 'lib',
formats: process.env.UNI_WATCH === 'true' ? 'umd' : 'umd-min',
entry: './lib/h5/main.js',
dest: path.join(pluginDir, 'dist'),
clean: true,
mode: process.env.NODE_ENV
}).then(function () {}).catch(err => {
error(err)
process.exit(1)
})

77
build/build.qa.js

@ -0,0 +1,77 @@
const fs = require('fs')
const del = require('del')
const path = require('path')
const copy = require('copy')
const rollup = require('rollup')
const genConfig = require('./rollup.config.qa')
const filename = 'vue.' + (process.env.NODE_ENV === 'production' ? 'prod' : 'dev') + '.js'
async function build () {
const bridgeBundle = await rollup.rollup(genConfig('bridge'))
const {
output: bridgeOutput
} = await bridgeBundle.generate({
format: 'iife'
})
const bridgeCode = bridgeOutput[0].code
const appBundle = await rollup.rollup(genConfig('app'))
const {
output: appOutput
} = await appBundle.generate({
format: 'iife',
banner: `
dsl.onInitApp(function({
inst,
context,
instRequireModule
}) {
if(!context.quickapp.dock.makeEvaluateBuildScript){
context.quickapp.dock.makeEvaluateBuildScript = args => args
}
const $app_require$ = instRequireModule;
`,
footer: `
});`
})
const appCode = appOutput[0].code
const pageBundle = await rollup.rollup(genConfig('page'))
const {
output: pageOutput
} = await pageBundle.generate({
format: 'iife',
banner: `
dsl.onInitPage(function({
$app_require$,
Vue
}) {
`,
footer: `
});`
})
const pageCode = pageOutput[0].code
const vueCode = fs.readFileSync(path.resolve(__dirname, '../packages/uni-quickapp-native/assets/' + filename))
fs.writeFileSync(
path.resolve(__dirname, '../packages/uni-quickapp-native/dist/' + filename),
vueCode + bridgeCode + appCode + pageCode, {
encoding: 'utf8'
}
)
if (process.env.NODE_ENV === 'production') { // 命令会执行dev,prod两次,仅prod时执行copy
const componentsSrc = path.resolve(__dirname, '../src/platforms/quickapp-native/view/components/**/*')
const componentsDest = path.resolve(__dirname, '../packages/uni-quickapp-native/components')
del.sync([componentsDest])
copy(componentsSrc, componentsDest, function (err, file) {
if (err) {
throw err
}
})
}
}
build()

18
build/fixInnerHTML.js

@ -0,0 +1,18 @@
const path = require('path')
const fs = require('fs')
module.exports = function () {
const files = [
path.join(__dirname, '../packages/uni-app-plus/dist/view.umd.min.js'),
path.join(__dirname, '../packages/uni-app-plus/template/v3/__uniappquill.js'),
path.join(__dirname, '../packages/uni-app-plus/template/v3/__uniappquillimageresize.js')
]
files.forEach(filePath => {
const fileContent = fs.readFileSync(filePath, {
encoding: 'utf8'
})
fs.writeFileSync(filePath, fileContent.replace(/\.innerHTML\b/g, '["inner"+"HTML"]'), {
encoding: 'utf8'
})
})
}

167
build/manifest.js

@ -0,0 +1,167 @@
const fs = require('fs')
const path = require('path')
const apis = require('../lib/apis')
const AUTO_LOADS = [
'upx2px',
'canIUse',
'getSystemInfo',
'getSystemInfoSync',
'navigateTo',
'redirectTo',
'switchTab',
'reLaunch',
'navigateBack'
]
const TOAST_DEPS = [
['/platforms/h5/components/app/popup/toast.vue', 'Toast'],
['/platforms/h5/components/app/popup/mixins/toast.js', 'ToastMixin']
]
// TODO 暂不考虑 head,tabBar 的动态拆分
const DEPS = {
chooseLocation: [
['/platforms/h5/view/components/map/index.vue', 'Map'],
['/core/view/components/input/index.vue', 'Input'],
['/core/view/components/scroll-view/index.vue', 'ScrollView'],
['/platforms/h5/service/api/network/request.js', 'request'],
['/platforms/h5/service/api/location/get-location.js', 'getLocation'],
['/platforms/h5/components/system-routes/choose-location/index.vue', 'ChooseLocation']
],
openLocation: [
['/platforms/h5/view/components/map/index.vue', 'Map'],
['/platforms/h5/service/api/network/request.js', 'request'],
['/platforms/h5/service/api/location/get-location.js', 'getLocation'],
['/platforms/h5/components/system-routes/open-location/index.vue', 'OpenLocation']
],
getLocation: [
['/platforms/h5/service/api/network/request.js', 'request']
],
previewImage: [
['/core/view/components/swiper/index.vue', 'Swiper'],
['/core/view/components/swiper-item/index.vue', 'SwiperItem'],
['/core/view/components/movable-area/index.vue', 'MovableArea'],
['/core/view/components/movable-view/index.vue', 'MovableView'],
[
'/platforms/h5/components/app/popup/preview-image/index.vue',
'PreviewImage'
],
[
'/platforms/h5/components/app/popup/mixins/preview-image.js',
'PreviewImageMixin'
]
],
showToast: TOAST_DEPS,
hideToast: TOAST_DEPS,
showLoading: TOAST_DEPS,
hideLoading: TOAST_DEPS,
showModal: [
['/platforms/h5/components/app/popup/modal.vue', 'Modal'],
['/platforms/h5/components/app/popup/mixins/modal.js', 'ModalMixin']
],
showActionSheet: [
['/platforms/h5/components/app/popup/actionSheet.vue', 'ActionSheet'],
['/platforms/h5/components/app/popup/mixins/action-sheet.js', 'ActionSheetMixin']
],
createSelectorQuery: [
['/core/view/bridge/subscribe/api/request-component-info.js', 'requestComponentInfo']
],
createIntersectionObserver: [
['/core/view/bridge/subscribe/api/request-component-observer.js', 'requestComponentObserver'],
['/core/view/bridge/subscribe/api/request-component-observer.js', 'destroyComponentObserver']
],
createMediaQueryObserver: [
['/core/view/bridge/subscribe/api/request-media-query-observer.js', 'requestMediaQueryObserver'],
['/core/view/bridge/subscribe/api/request-media-query-observer.js', 'destroyMediaQueryObserver']
]
}
// 检查依赖文件是否存在
Object.keys(DEPS).reduce(function (depFiles, name) {
DEPS[name].forEach(function (dep) {
depFiles.add(dep[0])
})
return depFiles
}, new Set()).forEach(file => {
if (!fs.existsSync(path.join(__dirname, '../src', file))) {
console.error(file + ' 不存在')
process.exit(0)
}
})
function parseApiManifestDeps (manifest, protocol) {
// 解析 platform 依赖
Object.keys(manifest).forEach(name => {
const deps = manifest[name][1]
if (deps.length) {
deps.forEach(dep => {
if (manifest[dep[1]]) {
dep[0] = manifest[dep[1]][0]
} else {
console.error(`依赖模块[${dep[1]}]不存在,删除 ${name} 接口\n`)
delete manifest[name]
}
})
}
})
// 解析 protocol 依赖
Object.keys(manifest).forEach(name => {
const deps = manifest[name][1]
if (protocol[name]) {
deps.push([protocol[name], name])
} else {
console.warn(`${name} 缺少 protocol`)
}
})
// 追加默认依赖
Object.keys(DEPS).forEach(name => {
if (manifest[name]) {
manifest[name][1].push(...DEPS[name])
} else {
console.error(`缺少 ${name}`)
}
})
// 设置自动加载标记
AUTO_LOADS.forEach(name => {
if (manifest[name]) {
manifest[name][2] = true
} else {
console.error(`缺少 ${name}`)
}
})
}
module.exports = {
generateApiManifest (manifest, protocol) {
if (!Object.keys(manifest).length) {
throw new Error('api manifest.json 生成失败')
}
parseApiManifestDeps(manifest, protocol)
const manifestJson = Object.create(null)
const todoApis = []
apis.forEach(name => {
if (manifest[name]) {
manifestJson[name] = manifest[name]
} else {
todoApis.push(name)
}
})
if (todoApis.length) {
console.log('\n')
console.warn(`${process.env.UNI_PLATFORM} 平台缺少以下 API 实现(共 ${todoApis.length} 个)`)
todoApis.forEach(name => {
console.warn(name)
})
}
fs.writeFileSync(path.resolve(__dirname, '../packages/uni-' + process.env.UNI_PLATFORM + '/manifest.json'),
JSON.stringify(manifestJson, null, 4)
)
}
}

30
build/postcssSplitMediaPlugin.js

@ -0,0 +1,30 @@
const mediaQuerys = []
module.exports = {
splitMediaPlugin: function (root, result) {
root.walkAtRules(rule => {
if (rule.params.indexOf('prefers-color-scheme') !== -1) {
root.removeChild(rule)
mediaQuerys.push(rule)
}
})
},
generateMediaQuerys: function ({ outputDir, filename = 'index.dark.css' }) {
if (mediaQuerys.length) {
const fs = require('fs')
const path = require('path')
const postcss = require('postcss')
const uglifycss = require('uglifycss')
const mediaRoot = postcss.root()
mediaRoot.append(mediaQuerys.sort((a, b) => a.source.input.file > b.source.input.file ? 1 : -1))
fs.writeFileSync(
path.resolve(outputDir, filename),
uglifycss.processString(mediaRoot.toResult().css),
{ encoding: 'utf-8', flag: 'w+' }
)
}
}
}

107
build/rollup.config.app.js

@ -0,0 +1,107 @@
const path = require('path')
const json = require('@rollup/plugin-json')
const alias = require('@rollup/plugin-alias')
const replace = require('@rollup/plugin-replace')
const nodeResolve = require('@rollup/plugin-node-resolve')
const commonjs = require('@rollup/plugin-commonjs')
const requireContext = require('../lib/rollup-plugin-require-context')
let input = 'src/platforms/app-plus/service/framework/create-instance-context.js'
const output = {
file: 'packages/uni-app-plus-nvue/dist/index.js',
format: 'es'
}
const external = []
// if (process.env.UNI_PLATFORM === 'app-plus-nvue') {
// external.push('vue')
// output.globals = {
// vue: 'Vue'
// }
// }
if (process.env.UNI_SERVICE === 'legacy') {
input = 'src/platforms/app-plus-nvue/services/index.legacy.js'
output.file = 'packages/uni-app-plus-nvue/dist/index.legacy.js'
} else {
input = 'src/platforms/app-plus/service/index.js'
if (process.env.UNI_PLATFORM === 'app-plus') {
output.file = 'packages/uni-app-plus/dist/index.v3.js'
} else {
output.file = 'packages/uni-app-plus-nvue/dist/index.js'
}
output.format = 'iife'
output.name = 'serviceContext'
output.banner =
`export function createServiceContext(Vue, weex, plus, UniServiceJSBridge,instanceContext){
var setTimeout = instanceContext.setTimeout
var clearTimeout = instanceContext.clearTimeout
var setInterval = instanceContext.setInterval
var clearInterval = instanceContext.clearInterval
var __uniConfig = instanceContext.__uniConfig
var __uniRoutes = instanceContext.__uniRoutes
`
output.footer =
`
var uni = serviceContext.uni
var getApp = serviceContext.getApp
var getCurrentPages = serviceContext.getCurrentPages
var __definePage = serviceContext.__definePage
var __registerPage = serviceContext.__registerPage
return serviceContext \n}
`
}
const resolve = dir => path.resolve(__dirname, '../', dir)
module.exports = {
input,
output,
plugins: [
alias({
entries: [{
find: '@dcloudio',
replacement: resolve('packages')
}, {
find: 'uni-core',
replacement: resolve('src/core')
}, {
find: 'uni-platform',
replacement: resolve('src/platforms/' + process.env.UNI_PLATFORM)
}, {
find: 'uni-platforms',
replacement: resolve('src/platforms')
}, {
find: 'uni-shared',
replacement: resolve('src/shared/index.js')
}, {
find: 'uni-helpers',
replacement: resolve('src/core/helpers')
}, {
find: 'uni-invoke-api',
replacement: resolve('src/platforms/app-plus/service/api')
}, {
find: 'uni-service-api',
replacement: resolve('src/core/service/platform-api')
}, {
find: 'uni-api-protocol',
replacement: resolve('src/core/helpers/protocol')
}]
}),
json(),
nodeResolve(),
requireContext(),
commonjs(),
replace({
__GLOBAL__: 'getGlobalUni()',
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM),
__PLATFORM_TITLE__: 'app-plus-nvue'
})
],
external
}

106
build/rollup.config.mp.js

@ -0,0 +1,106 @@
const path = require('path')
const json = require('@rollup/plugin-json')
const alias = require('@rollup/plugin-alias')
const replace = require('@rollup/plugin-replace')
const PLATFORMS = {
'mp-weixin': {
prefix: 'wx',
title: '微信小程序'
},
'mp-qq': {
prefix: 'wx',
title: 'QQ小程序'
},
'mp-alipay': {
prefix: 'my',
title: '支付宝小程序'
},
'mp-baidu': {
prefix: 'swan',
title: '百度小程序'
},
'mp-toutiao': {
prefix: 'tt',
title: '头条小程序'
},
'mp-kuaishou': {
prefix: 'ks',
title: '快手小程序'
},
'mp-lark': {
prefix: 'tt',
title: '飞书小程序'
},
'mp-jd': {
prefix: 'jd',
title: '京东小程序'
},
'mp-xhs': {
prefix: 'xhs',
title: '小红书小程序'
},
'quickapp-webview': {
prefix: 'qa',
title: '快应用(Webview)版'
},
'app-plus': {
prefix: 'wx',
title: 'app-plus'
}
}
const platform = PLATFORMS[process.env.UNI_PLATFORM]
let input = 'src/core/runtime/index.js'
const output = {
file: `packages/uni-${process.env.UNI_PLATFORM}/dist/index.js`,
format: 'es'
}
if (process.env.UNI_MP) {
input = 'src/core/runtime/mp/index.js'
output.file = `packages/uni-${process.env.UNI_PLATFORM}/dist/mp.js`
}
module.exports = {
input,
output,
plugins: [
alias({
entries: [{
find: '@dcloudio',
replacement: path.resolve(__dirname, '../packages')
}, {
find: 'uni-core',
replacement: path.resolve(__dirname, '../src/core')
}, {
find: 'uni-api-protocol',
replacement: path.resolve(__dirname, '../src/core/helpers/protocol')
}, {
find: 'uni-shared/query',
replacement: path.resolve(__dirname, '../src/shared/query.js')
}, {
find: 'uni-shared',
replacement: path.resolve(__dirname, '../src/shared/util.js')
}, {
find: 'uni-platform',
replacement: path.resolve(__dirname, '../src/platforms/' + process.env.UNI_PLATFORM)
}, {
find: 'uni-wrapper',
replacement: path.resolve(__dirname, '../src/core/runtime/wrapper')
}, {
find: 'uni-helpers',
replacement: path.resolve(__dirname, '../src/core/helpers')
}]
}),
json(),
replace({
__GLOBAL__: platform.prefix,
__PLATFORM_TITLE__: platform.title,
__PLATFORM_PREFIX__: JSON.stringify(platform.prefix),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM)
})
],
external: ['vue', '@dcloudio/uni-i18n']
}

94
build/rollup.config.qa.js

@ -0,0 +1,94 @@
const path = require('path')
const json = require('@rollup/plugin-json')
const alias = require('@rollup/plugin-alias')
const replace = require('@rollup/plugin-replace')
const nodeResolve = require('@rollup/plugin-node-resolve')
const commonjs = require('@rollup/plugin-commonjs')
const terser = require('rollup-plugin-terser')
const requireContext = require('../lib/rollup-plugin-require-context')
process.env.UNI_PLATFORM = 'quickapp-native'
const external = []
const resolve = dir => path.resolve(__dirname, '../', dir)
function replaceModuleImport (str) {
return str.replace(
/require\s*\(\s*(['"])@([\w$_][\w$-.]*?)\1\)/gm,
(e, r, p) => `$app_require$(${r}@app-module/${p}${r})`
).replace(
/import\s+([\w${}]+?)\s+from\s+(['"])@([\w$_][\w$-.]*?)\2/gm,
(e, r, p, t) => `var ${r} = $app_require$(${p}@app-module/${t}${p})`
)
}
const plugins = [{
name: 'replaceModuleImport',
transform (source) {
return {
code: replaceModuleImport(source)
}
}
},
alias({
entries: [{
find: '@dcloudio',
replacement: resolve('packages')
}, {
find: 'uni-core',
replacement: resolve('src/core')
}, {
find: 'uni-platform',
replacement: resolve('src/platforms/quickapp-native')
}, {
find: 'uni-platforms',
replacement: resolve('src/platforms')
}, {
find: 'uni-shared',
replacement: resolve('src/shared/index.js')
}, {
find: 'uni-helpers',
replacement: resolve('src/core/helpers')
}, {
find: 'uni-invoke-api',
replacement: resolve('src/platforms/quickapp-native/service/invoke-api')
}, {
find: 'uni-service-api',
replacement: resolve('src/platforms/quickapp-native/service/api')
}, {
find: 'uni-api-protocol',
replacement: resolve('src/core/helpers/protocol')
}]
}),
json(),
nodeResolve(),
requireContext(),
commonjs(),
replace({
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM),
__PLATFORM_TITLE__: '快应用(Native)版'
})
]
// if (process.env.NODE_ENV === 'production') {
plugins.push(terser.terser())
// }
module.exports = function (type) {
let input = ''
if (type === 'bridge') {
input = 'src/platforms/quickapp-native/runtime/bridge.js'
} else if (type === 'app') {
input = 'src/platforms/quickapp-native/runtime/app.js'
} else if (type === 'page') {
input = 'src/platforms/quickapp-native/runtime/page.js'
}
return {
input,
plugins,
external
}
}

38
build/rollup.config.service.js

@ -0,0 +1,38 @@
const path = require('path')
const json = require('@rollup/plugin-json')
const alias = require('@rollup/plugin-alias')
const replace = require('@rollup/plugin-replace')
module.exports = {
input: 'src/platforms/app-plus-nvue/services/index.legacy.old.js',
output: {
file: 'packages/uni-app-plus-nvue/dist/service.legacy.js',
format: 'es'
},
plugins: [
alias({
entries: [{
find: '@dcloudio',
replacement: path.resolve(__dirname, '../packages')
},
{
find: 'uni-core',
replacement: path.resolve(__dirname, '../src/core')
},
{
find: 'uni-shared',
replacement: path.resolve(__dirname, '../src/shared/util.js')
},
{
find: 'uni-helpers',
replacement: path.resolve(__dirname, '../src/core/helpers')
}
]
}),
json(),
replace({
__GLOBAL__: 'getGlobalUni()',
__PLATFORM_TITLE__: 'app-plus-nvue'
})
]
}

20
build/rollup.config.stat.js

@ -0,0 +1,20 @@
module.exports = [
{
input: 'packages/uni-stat/src/index.js',
output: {
file: 'packages/uni-stat/dist/index.js',
format: 'es'
},
external: ['vue', '../package.json'],
plugins: []
},
{
input: 'packages/uni-cloud-stat/src/index.js',
output: {
file: 'packages/uni-cloud-stat/dist/index.js',
format: 'es'
},
external: ['vue', '../package.json'],
plugins: []
}
]

25
build/rollup.config.web-view.js

@ -0,0 +1,25 @@
const path = require('path')
const babel = require('rollup-plugin-babel')
const alias = require('@rollup/plugin-alias')
const terser = require('rollup-plugin-terser')
module.exports = {
input: 'src/core/runtime/web-view/index.js',
output: {
name: 'uni',
file: 'dist/uni.webview.1.5.5.js',
format: 'umd'
},
plugins: [
alias({
entries: [{
find: 'uni-shared',
replacement: path.resolve(__dirname, '../src/shared/index.js')
}, {
find: 'uni-platforms',
replacement: path.resolve(__dirname, '../src/platforms')
}]
}),
babel(),
terser.terser()
]
}

7
build/rollup.config.wxs.js

@ -0,0 +1,7 @@
module.exports = {
input: 'src/core/runtime/mp/wxs.js',
output: {
file: 'packages/uni-mp-weixin/dist/wxs.js',
format: 'es'
}
}

69
build/vue.config.js

@ -0,0 +1,69 @@
const path = require('path')
const resolve = dir => path.resolve(__dirname, '../', dir)
const pkgPath = resolve('package.json')
const { splitMediaPlugin, generateMediaQuerys } = require('./postcssSplitMediaPlugin')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config.js')
const postCssConfig = require('../postcss.config')
let outputDir = resolve('./packages/uni-' + process.env.UNI_PLATFORM + '/dist')
if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_UI === 'true') {
outputDir = resolve('./packages/uni-' + process.env.UNI_PLATFORM + '-ui/dist')
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true') {
outputDir = resolve('./packages/uni-' + process.env.UNI_PLATFORM + '/dist')
}
if (process.env.UNI_PLATFORM === 'h5') { postCssConfig.plugins.push(splitMediaPlugin) }
module.exports = {
publicPath: '/',
outputDir,
lintOnSave: true, // or error
runtimeCompiler: false,
transpileDependencies: ['@dcloudio/uni-i18n'],
productionSourceMap: false,
configureWebpack: webpackConfig,
parallel: process.env.UNI_PLATFORM !== 'h5' || process.env.UNI_WATCH !== 'false' || process.env.UNI_UI === 'true',
chainWebpack: config => {
config.devtool('source-map')
config.module
.rule('eslint')
.include
.add(resolve('src'))
.add(resolve('lib/' + process.env.UNI_PLATFORM))
.end()
.use('eslint-loader')
.loader(resolve('node_modules/eslint-loader'))
.options({
fix: true,
configFile: pkgPath
})
config.plugins.delete('hmr') // remove hot module reload
if (process.env.UNI_PLATFORM === 'h5') {
config
.plugin('webpack-build-done')
.use(webpack.ProgressPlugin, [function (percentage, message, ...args) {
if (percentage === 1) {
generateMediaQuerys({
outputDir
})
}
}])
}
},
css: {
extract: true,
loaderOptions: {
postcss: postCssConfig
}
}
}

80
build/webpack.config.js

@ -0,0 +1,80 @@
const path = require('path')
const webpack = require('webpack')
const resolve = dir => path.resolve(__dirname, '../', dir)
const pkg = require('../package.json')
const externals = {}
if (process.env.UNI_VIEW !== 'true') {
externals.vue = {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
}
externals['vue-router'] = {
commonjs: 'vue-router',
commonjs2: 'vue-router',
root: 'VueRouter'
}
externals['@dcloudio/uni-i18n'] = {
commonjs: '@dcloudio/uni-i18n',
commonjs2: '@dcloudio/uni-i18n',
root: '@dcloudio/uni-i18n'
}
}
const alias = {
'@dcloudio': resolve('packages'),
'uni-core': resolve('src/core'),
'uni-view': resolve('src/core/view'),
'uni-service': resolve('src/core/service'),
'uni-shared': resolve('src/shared'),
'uni-mixins': resolve('src/core/view/mixins'),
'uni-helpers': resolve('src/core/helpers'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
// tree shaking
'uni-components': resolve('src/core/view/components'),
'uni-invoke-api': resolve('src/platforms/' + process.env.UNI_PLATFORM + '/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol'),
'uni-api-subscribe': resolve('src/core/view/bridge/subscribe/api/index'),
// h5 components
'uni-h5-app-components': resolve('src/platforms/h5/components/app/popup/index'),
'uni-h5-app-mixins': resolve('src/platforms/h5/components/app/popup/mixins/index'),
'uni-h5-system-routes': resolve('src/platforms/h5/components/system-routes/index')
}
const provides = {
console: [resolve('src/core/helpers/console'), 'default'],
UniViewJSBridge: [resolve('src/core/view/bridge/index')],
UniServiceJSBridge: [resolve('src/core/service/bridge/index')]
}
if (process.env.UNI_VIEW) { // 方便调试
delete provides.console
}
if (process.env.UNI_VIEW === 'true') {
alias.vue$ = resolve('packages/vue-cli-plugin-uni/packages/h5-vue/dist/vue.runtime.esm.js')
}
module.exports = {
mode: 'production',
devtool: false,
externals,
resolve: {
alias
},
module: {
rules: []
},
plugins: [
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(pkg.version),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM),
__VIEW__: JSON.stringify(!!process.env.UNI_VIEW)
}),
new webpack.ProvidePlugin(provides)
]
}

58
build/webpack.config.test.js

@ -0,0 +1,58 @@
const path = require('path')
const webpack = require('webpack')
const resolve = dir => path.resolve(__dirname, '../', dir)
const pkg = require('../package.json')
let service = process.VUE_CLI_SERVICE
if (!service || process.env.VUE_CLI_API_MODE) {
const Service = require('@vue/cli-service')
service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
service.init(process.env.VUE_CLI_MODE || process.env.NODE_ENV)
}
const config = service.resolveWebpackConfig()
config.resolve.alias = {
'@': resolve('src'),
'@dcloudio': resolve('packages'),
'uni-core': resolve('src/core'),
'uni-view': resolve('src/core/view'),
'uni-service': resolve('src/core/service'),
'uni-shared': resolve('src/shared'),
'uni-mixins': resolve('src/core/view/mixins'),
'uni-helpers': resolve('src/core/helpers'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
// tree shaking
'uni-components': resolve('src/core/view/components'),
'uni-invoke-api': resolve('src/platforms/' + process.env.UNI_PLATFORM + '/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol'),
'uni-api-subscribe': resolve('src/core/view/bridge/subscribe/api/index'),
// h5 components
'uni-h5-app-components': resolve('src/platforms/h5/components/app/popup/index'),
'uni-h5-app-mixins': resolve('src/platforms/h5/components/app/popup/mixins/index'),
'uni-h5-system-routes': resolve('src/platforms/h5/components/system-routes/index')
}
const isEslintLoader = config.module.rules[config.module.rules.length - 1].enforce
if (isEslintLoader) {
config.module.rules.splice(config.module.rules.length - 1, 1)
} else {
throw new Error('eslint-loader is undefined')
}
config.plugins = config.plugins.concat([
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(pkg.version),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM)
}),
new webpack.ProvidePlugin({
console: [resolve('src/core/helpers/console'), 'default'],
UniViewJSBridge: [resolve('src/core/view/bridge/index')],
UniServiceJSBridge: [resolve('src/core/service/bridge/index')]
})
])
module.exports = config

21
check-version.js

@ -0,0 +1,21 @@
const fs = require('fs')
const path = require('path')
const request = require('request')
const registry = 'https://registry.npmjs.org/@dcloudio/'
const pkgs = fs.readdirSync(path.resolve(__dirname, 'packages')).filter(pkg => pkg.indexOf('.') !== 0)
const tag = process.argv[2] || 'alpha'
pkgs.forEach(pkg => {
request(registry + pkg, function(error, response, body) {
if (error) {
console.log(pkg, error)
} else {
const version = JSON.parse(body)['dist-tags'][tag]
console.log(pkg + ':' + (' '.repeat(80 - (pkg + ':' + version).length)) + version)
}
})
})

17
dist-tag-latest.js

@ -0,0 +1,17 @@
const fs = require('fs')
const path = require('path')
const shellExec = require('shell-exec')
const pkgs = fs.readdirSync(path.resolve(__dirname, 'packages')).filter(pkg => pkg.indexOf('.') !== 0)
const version = process.argv[2]
if (!version) {
throw new Error('必须传入 version')
}
(async function() {
for (let i = 0; i < pkgs.length; i++) {
console.log(`npm dist-tag add @dcloudio/${pkgs[i]}@${version} latest`);
await shellExec(`npm dist-tag add @dcloudio/${pkgs[i]}@${version} latest`)
}
})();

1
dist/uni.webview.1.5.2.js

@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));

1
dist/uni.webview.1.5.3.js

File diff suppressed because one or more lines are too long

1
dist/uni.webview.1.5.4.js

File diff suppressed because one or more lines are too long

1
dist/uni.webview.1.5.5.js

File diff suppressed because one or more lines are too long

2
docs/README.md

@ -0,0 +1,2 @@
* [简体中文](https://github.com/dcloudio/unidocs-zh)
* [English](https://github.com/dcloudio/unidocs-en)

1
examples/hello-uniapp/README.md

@ -0,0 +1 @@
代码已迁移,请移步[https://github.com/dcloudio/hello-uniapp](https://github.com/dcloudio/hello-uniapp)查看最新代码

1
examples/image-template/README.md

@ -0,0 +1 @@
代码已迁移,请移步[https://github.com/dcloudio/uni-template-picture](https://github.com/dcloudio/uni-template-picture)查看最新代码

1
examples/login-template/README.md

@ -0,0 +1 @@
代码已迁移,请移步[https://github.com/dcloudio/uni-template-login](https://github.com/dcloudio/uni-template-login)查看最新代码

75
examples/uniapp-one/App.vue

@ -0,0 +1,75 @@
<script>
import { mapActions, mapMutations } from 'vuex'
export default {
created () {
this.initPage()
},
methods: {
...mapMutations('weather', {
setLocation: 'SET_LOCATION'
}),
...mapActions('weather', ['getWeather']),
async initPage() {
const location = await this.getLocation()
this.setLocation({
location
})
this.getWeather()
},
async getLocation() {
return await new Promise((resolve, reject) => {
wx.getLocation({
success(location) {
resolve(location)
},
fail(err) {
console.log(err)
reject(err)
}
})
})
}
}
}
</script>
<style>
.container {
font-size: 26rpx;
text-align: center;
}
.wrapper {
font-size: 26rpx;
text-align: left;
}
* {
transition: width 2s;
-moz-transition: width 2s;
-webkit-transition: width 2s;
-o-transition: width 2s;
}
/* font color */
* {
color: #353535;
}
.gray {
color: #808080;
}
.wxParse {
text-indent: 2em;
}
.wxParse image {
text-indent: 0;
}
.wxParse ._view {
padding: 0 10rpx;
text-indent: 0;
}
.wxParse .p {
text-indent: 1em;
}
</style>

11
examples/uniapp-one/README.md

@ -0,0 +1,11 @@
# uni-one
> 使用uni-app开发的 [「ONE · 一个」](http://wufazhuce.com)
> 移植自[mpvue-one](https://github.com/feng-fu/mpvue-one/blob/master/README.md)
> 本项目仅作为mpvue项目移植示例
## 使用方式
将项目拖入[HbuilderX](http://www.dcloud.io/hbuilderx.html),直接运行即可
## 注意事项
* 在小程序中预览提示合法域名校验出错,需打开微信开发者工具内 设置-项目设置,勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”。

64
examples/uniapp-one/components/article.vue

@ -0,0 +1,64 @@
<template>
<block>
<view class="title">
<text>{{title}}</text>
</view>
<view class="author" v-if="user_name">
<text> / {{user_name}}</text>
</view>
<view class="summary" v-if="summary">
<view class="line"></view>
<text>{{summary}}</text>
</view>
<wx-parse :content="content"></wx-parse>
</block>
</template>
<script>
import wxParse from './mpvue-wxparse/wxParse.vue'
export default {
props: {
title: String,
user_name: String,
content: String,
summary: String
},
components: {
wxParse
}
}
</script>
<style scoped>
.title {
font-size: 36rpx;
font-weight: 700;
margin: .8em .8em;
text-align: center;
}
.author {
color: #cacaca;
font-size: 24rpx;
text-align: right;
padding-right: 2em;
}
.summary {
position: relative;
color: #b0b0b0;
font-size: 24rpx;
white-space: nowrap;
text-overflow: ellipse;
padding-left: 40rpx;
height: 60rpx;
line-height: 60rpx;
}
.summary .line {
position: absolute;
top: 14rpx;
left: 20rpx;
width: 10rpx;
height: 32rpx;
background-color: #d0d0d0;
}
</style>

89
examples/uniapp-one/components/movieItem.vue

@ -0,0 +1,89 @@
<template>
<block>
<view class="list-container" v-if="movie.subtitle">
<view class="content">
<view class="view-title title">
<text>{{movie.title}}</text>
</view>
<view class="author">
<!-- <text>{{movie.author_list[0].user_name}} </text> -->
<!-- <text>{{movie.author_list[0].desc}}</text> -->
<text>{{movie.subtitle}}</text>
</view>
</view>
<view>
<image class="avatar" :src="movie.img_url || 'https://petrify.oss-cn-beijing.aliyuncs.com/arrow-right.png'" />
</view>
</view>
<block v-else>
<view class="only-title title">
<text>{{movie.title}}</text>
<image class="arraw" src="https://petrify.oss-cn-beijing.aliyuncs.com/arrow-right.png" />
</view>
</block>
</block>
</template>
<script>
export default {
props: {
movie: Object
}
}
</script>
<style>
.title {
font-size: 28rpx;
line-height: 40rpx;
margin-bottom: 10rpx;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.only-title {
height: 100%;
line-height: 170rpx;
text-align: left;
padding-left: 20rpx;
display: flex;
align-items: center;
}
.only-title text {
width: 680rpx;
}
.arraw {
width: 28rpx;
height: 28rpx;
}
.view-title {
text-align: left;
}
.avatar {
width: 100rpx;
height: 100rpx;
padding-right: 20rpx;
}
.list-container {
display: flex;
align-items: center;
height: 100%;
padding-left: 20rpx;
}
.content {
width: 600rpx;
}
.author {
text-align: left;
color: #979794;
}
</style>

97
examples/uniapp-one/components/mpvue-wxparse/components/wxParseImg.vue

@ -0,0 +1,97 @@
<template>
<image
class="img"
:mode="node.image.mode"
:lazy-load="node.image.lazyLoad"
:class="node.classStr"
:style="fitStyleStr"
:data-src="node.attr.src"
:src="node.attr.src"
@tap="wxParseImgTap"
@load="wxParseImgLoad"
/>
</template>
<script>
export default {
name: 'wxParseImg',
data() {
return {
realWindowWidth: 0,
realWindowHeight: 0,
newStyleStr: '',
};
},
props: {
node: {
type: Object,
default() {
return {};
},
},
},
mounted() {
this.getSysWH();
},
computed: {
fitStyleStr() {
return this.newStyleStr || this.node.styleStr;
},
},
methods: {
getSysWH() {
// , 便, wxParse.vue
wx.getSystemInfo({
success: (res) => {
this.realWindowWidth = res.windowWidth;
this.realWindowHeight = res.windowHeight;
},
});
},
wxParseImgTap(e) {
const { src } = e.target.dataset;
if (!src) return;
wx.previewImage({
current: src, // http
urls: this.node.image.urls, // http
});
},
//
wxParseImgLoad(e) {
const { src } = e.target.dataset;
if (!src) return;
if (typeof src !== 'undefined' && src !== '' && src !== null) {
this.calMoreImageInfo(e);
}
},
//
calMoreImageInfo(e) {
const { width, height } = e.mp.detail;
const recal = this.wxAutoImageCal(width, height);
const { imageheight, imageWidth } = recal;
const { padding } = this.node.image;
this.newStyleStr = `height: ${imageheight}px; width: ${imageWidth}px; padding: 0 ${padding}px;`;
},
//
wxAutoImageCal(originalWidth, originalHeight) {
//
const { padding } = this.node.image;
const windowWidth = this.realWindowWidth - (2 * padding);
const results = {};
//
if (originalWidth > windowWidth) {
// widthwidth
results.imageWidth = windowWidth;
results.imageheight = windowWidth * (originalHeight / originalWidth);
} else {
//
results.imageWidth = originalWidth;
results.imageheight = originalHeight;
}
return results;
},
},
};
</script>

101
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate0.vue

@ -0,0 +1,101 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--table类型-->
<block v-else-if="node.tag == 'table'">
<view :class="node.classStr" class="table" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate1';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate0',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate1.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate2';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate1',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate10.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate11';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate10',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

80
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate11.vue

@ -0,0 +1,80 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
{{node.text}}
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
{{node.text}}
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
{{node.text}}
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
{{node.text}}
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate11',
props: {
node: {},
},
components: {
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate2.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate3';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate2',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate3.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate4';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate3',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate4.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate5';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate4',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate5.vue

@ -0,0 +1,92 @@
s<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate6';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate5',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate6.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate7';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate6',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate7.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate8';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate7',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate8.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate9';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate8',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

92
examples/uniapp-one/components/mpvue-wxparse/components/wxParseTemplate9.vue

@ -0,0 +1,92 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<block v-if="node.tag == 'button'">
<button type="default" size="mini">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="node.tag == 'li'">
<view :class="node.classStr" class="li" :style="node.styleStr">
<view :class="node.classStr" class="li-inner">
<view :class="node.classStr" class="li-text">
<view :class="node.classStr" class="li-circle"></view>
</view>
<view :class="node.classStr" class="li-text">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="node.tag == 'video'">
<wx-parse-video :node="node" />
</block>
<!--img类型-->
<block v-else-if="node.tag == 'img'">
<wx-parse-img :node="node" />
</block>
<!--a类型-->
<block v-else-if="node.tag == 'a'">
<view :class="node.classStr" class="inline a" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--br类型-->
<block v-else-if="node.tag == 'br'">
<text>\n</text>
</block>
<!--其他块级标签-->
<block v-else-if="node.tagType == 'block' && node.tag !== 'script'">
<view :class="[node.classStr, node.tag]" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--内联标签-->
<view v-else-if="node.tagType == 'inline' && node.tag !== 'style'" :class="[node.classStr, node.tag]" class="inline" :style="node.styleStr">
<block v-for="node of node.nodes" :key="node.index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">
{{node.text}}
</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate10';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
export default {
name: 'wxParseTemplate9',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
},
};
</script>

15
examples/uniapp-one/components/mpvue-wxparse/components/wxParseVideo.vue

@ -0,0 +1,15 @@
<template>
<!--增加video标签支持并循环添加-->
<view :class="node.classStr" class="video" :style="node.styleStr">
<video :class="node.classStr" class="video-video" :src="node.attr.src"></video>
</view>
</template>
<script>
export default {
name: 'wxParseVideo',
props: {
node: {},
},
};
</script>

252
examples/uniapp-one/components/mpvue-wxparse/libs/html2json.js

@ -0,0 +1,252 @@
/**
* html2Json 改造来自: https://github.com/Jxck/html2json
*
*
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
import wxDiscode from './wxDiscode';
import HTMLParser from './htmlparser';
const placeImgeUrlHttps = 'https';
function makeMap(str) {
const obj = {};
const items = str.split(',');
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
return obj;
}
// Block Elements - HTML 5
const block = makeMap('br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
// Inline Elements - HTML 5
const inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
// Elements that you can, intentionally, leave open
// (and which close themselves)
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
function removeDOCTYPE(html) {
return html
.replace(/<\?xml.*\\?>\n/, '')
.replace(/<.*!doctype.*\\>\n/, '')
.replace(/<.*!DOCTYPE.*\\>\n/, '');
}
function trimHtml(html) {
return html
.replace(/<!--.*?-->/gi, '')
.replace(/\/\*.*?\*\//gi, '')
.replace(/[ ]+</gi, '<');
}
function html2json(html, image, debug) {
// 处理字符串
html = removeDOCTYPE(html);
html = trimHtml(html);
html = wxDiscode.strDiscode(html);
// 生成node节点
const bufArray = [];
const results = {
nodes: [],
images: [],
imageUrls: [],
};
let index = 0;
image.urls = results.imageUrls;
HTMLParser(html, {
start(tag, attrs, unary) {
// node for this element
const node = {
node: 'element',
tag,
};
if (bufArray.length === 0) {
node.index = index.toString();
index += 1;
} else {
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
node.index = `${parent.index}.${parent.nodes.length}`;
}
if (block[tag]) {
node.tagType = 'block';
} else if (inline[tag]) {
node.tagType = 'inline';
} else if (closeSelf[tag]) {
node.tagType = 'closeSelf';
}
node.attr = attrs.reduce((pre, attr) => {
const { name } = attr;
let { value } = attr;
if (name === 'class') {
if (debug) console.dir(value);
// value = value.join("")
node.classStr = value;
}
// has multi attibutes
// make it array of attribute
if (name === 'style') {
if (debug) console.dir(value);
// value = value.join("")
node.styleStr = value;
}
if (value.match(/ /)) {
value = value.split(' ');
}
// if attr already exists
// merge it
if (pre[name]) {
if (Array.isArray(pre[name])) {
// already array, push to last
pre[name].push(value);
} else {
// single value, make it array
pre[name] = [pre[name], value];
}
} else {
// not exist, put it
pre[name] = value;
}
return pre;
}, {});
// 对img添加额外数据
if (node.tag === 'img') {
node.imgIndex = results.images.length;
let imgUrl = node.attr.src;
imgUrl = wxDiscode.urlToHttpUrl(imgUrl, placeImgeUrlHttps);
node.attr.src = imgUrl || '';
node.image = image;
if (imgUrl) {
results.images.push(node);
results.imageUrls.push(imgUrl);
}
}
// 处理a标签属性
if (node.tag === 'a') {
node.attr.href = node.attr.href || '';
}
// 处理font标签样式属性
if (node.tag === 'font') {
const fontSize = [
'x-small',
'small',
'medium',
'large',
'x-large',
'xx-large',
'-webkit-xxx-large',
];
const styleAttrs = {
color: 'color',
face: 'font-family',
size: 'font-size',
};
if (!node.attr.style) node.attr.style = [];
if (!node.styleStr) node.styleStr = '';
Object.keys(styleAttrs).forEach((key) => {
if (node.attr[key]) {
const value = key === 'size' ? fontSize[node.attr[key] - 1] : node.attr[key];
node.attr.style.push(styleAttrs[key]);
node.attr.style.push(value);
node.styleStr += `${styleAttrs[key]}: ${value};`;
}
});
}
// 临时记录source资源
if (node.tag === 'source') {
results.source = node.attr.src;
}
if (unary) {
// if this tag doesn't have end tag
// like <img src="hoge.png"/>
// add to parents
const parent = bufArray[0] || results;
if (parent.nodes === undefined) {
parent.nodes = [];
}
parent.nodes.push(node);
} else {
bufArray.unshift(node);
}
},
end(tag) {
// merge into parent tag
const node = bufArray.shift();
if (node.tag !== tag && debug) {
console.error('invalid state: mismatch end tag');
}
// 当有缓存source资源时于于video补上src资源
if (node.tag === 'video' && results.source) {
node.attr.src = results.source;
delete results.source;
}
if (bufArray.length === 0) {
results.nodes.push(node);
} else {
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
parent.nodes.push(node);
}
},
chars(text) {
const node = {
node: 'text',
text: text.trim(),
};
if (bufArray.length === 0) {
node.index = index.toString();
index += 1;
results.nodes.push(node);
} else {
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
node.index = `${parent.index}.${parent.nodes.length}`;
parent.nodes.push(node);
}
},
comment(text) {
const node = {
node: 'comment',
text,
};
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
parent.nodes.push(node);
},
});
return results;
}
export default html2json;

188
examples/uniapp-one/components/mpvue-wxparse/libs/htmlparser.js

@ -0,0 +1,188 @@
/**
*
* htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
*
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
// Regular Expressions for parsing tags and attributes
const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
function makeMap(str) {
const obj = {};
const items = str.split(',');
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
return obj;
}
// Empty Elements - HTML 5
const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
// Block Elements - HTML 5
const block = makeMap('a,address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
// Inline Elements - HTML 5
const inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
// Elements that you can, intentionally, leave open
// (and which close themselves)
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
// Attributes that have their values filled in disabled="disabled"
const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
// Special Elements (can contain anything)
const special = makeMap('script,style,view,scroll-view,block');
function HTMLParser(html, handler) {
let index;
let chars;
let match;
let last = html;
const stack = [];
stack.last = () => stack[stack.length - 1];
function parseEndTag(tag, tagName) {
// If no tag name is provided, clean shop
let pos;
if (!tagName) {
pos = 0;
} else {
// Find the closest opened tag of the same type
tagName = tagName.toLowerCase();
for (pos = stack.length - 1; pos >= 0; pos -= 1) {
if (stack[pos] === tagName) break;
}
}
if (pos >= 0) {
// Close all the open elements, up the stack
for (let i = stack.length - 1; i >= pos; i -= 1) {
if (handler.end) handler.end(stack[i]);
}
// Remove the open elements from the stack
stack.length = pos;
}
}
function parseStartTag(tag, tagName, rest, unary) {
tagName = tagName.toLowerCase();
if (block[tagName]) {
while (stack.last() && inline[stack.last()]) {
parseEndTag('', stack.last());
}
}
if (closeSelf[tagName] && stack.last() === tagName) {
parseEndTag('', tagName);
}
unary = empty[tagName] || !!unary;
if (!unary) stack.push(tagName);
if (handler.start) {
const attrs = [];
rest.replace(attr, function genAttr(matches, name) {
const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
attrs.push({
name,
value,
escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
});
});
if (handler.start) {
handler.start(tagName, attrs, unary);
}
}
}
while (html) {
chars = true;
// Make sure we're not in a script or style element
if (!stack.last() || !special[stack.last()]) {
// Comment
if (html.indexOf('<!--') === 0) {
index = html.indexOf('-->');
if (index >= 0) {
if (handler.comment) handler.comment(html.substring(4, index));
html = html.substring(index + 3);
chars = false;
}
// end tag
} else if (html.indexOf('</') === 0) {
match = html.match(endTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(endTag, parseEndTag);
chars = false;
}
// start tag
} else if (html.indexOf('<') === 0) {
match = html.match(startTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(startTag, parseStartTag);
chars = false;
}
}
if (chars) {
index = html.indexOf('<');
let text = '';
while (index === 0) {
text += '<';
html = html.substring(1);
index = html.indexOf('<');
}
text += index < 0 ? html : html.substring(0, index);
html = index < 0 ? '' : html.substring(index);
if (handler.chars) handler.chars(text);
}
} else {
html = html.replace(
new RegExp(`([\\s\\S]*?)</${stack.last()}[^>]*>`),
(all, text) => {
text = text.replace(
/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g,
'$1$2',
);
if (handler.chars) handler.chars(text);
return '';
},
);
parseEndTag('', stack.last());
}
if (html === last) throw new Error(`Parse Error: ${html}`);
last = html;
}
// Clean up any remaining tags
parseEndTag();
}
export default HTMLParser;

197
examples/uniapp-one/components/mpvue-wxparse/libs/wxDiscode.js

@ -0,0 +1,197 @@
// HTML 支持的数学符号
function strNumDiscode(str) {
str = str.replace(/&forall;/g, '∀');
str = str.replace(/&part;/g, '∂');
str = str.replace(/&exist;/g, '∃');
str = str.replace(/&empty;/g, '∅');
str = str.replace(/&nabla;/g, '∇');
str = str.replace(/&isin;/g, '∈');
str = str.replace(/&notin;/g, '∉');
str = str.replace(/&ni;/g, '∋');
str = str.replace(/&prod;/g, '∏');
str = str.replace(/&sum;/g, '∑');
str = str.replace(/&minus;/g, '−');
str = str.replace(/&lowast;/g, '∗');
str = str.replace(/&radic;/g, '√');
str = str.replace(/&prop;/g, '∝');
str = str.replace(/&infin;/g, '∞');
str = str.replace(/&ang;/g, '∠');
str = str.replace(/&and;/g, '∧');
str = str.replace(/&or;/g, '∨');
str = str.replace(/&cap;/g, '∩');
str = str.replace(/&cup;/g, '∪');
str = str.replace(/&int;/g, '∫');
str = str.replace(/&there4;/g, '∴');
str = str.replace(/&sim;/g, '∼');
str = str.replace(/&cong;/g, '≅');
str = str.replace(/&asymp;/g, '≈');
str = str.replace(/&ne;/g, '≠');
str = str.replace(/&le;/g, '≤');
str = str.replace(/&ge;/g, '≥');
str = str.replace(/&sub;/g, '⊂');
str = str.replace(/&sup;/g, '⊃');
str = str.replace(/&nsub;/g, '⊄');
str = str.replace(/&sube;/g, '⊆');
str = str.replace(/&supe;/g, '⊇');
str = str.replace(/&oplus;/g, '⊕');
str = str.replace(/&otimes;/g, '⊗');
str = str.replace(/&perp;/g, '⊥');
str = str.replace(/&sdot;/g, '⋅');
return str;
}
// HTML 支持的希腊字母
function strGreeceDiscode(str) {
str = str.replace(/&Alpha;/g, 'Α');
str = str.replace(/&Beta;/g, 'Β');
str = str.replace(/&Gamma;/g, 'Γ');
str = str.replace(/&Delta;/g, 'Δ');
str = str.replace(/&Epsilon;/g, 'Ε');
str = str.replace(/&Zeta;/g, 'Ζ');
str = str.replace(/&Eta;/g, 'Η');
str = str.replace(/&Theta;/g, 'Θ');
str = str.replace(/&Iota;/g, 'Ι');
str = str.replace(/&Kappa;/g, 'Κ');
str = str.replace(/&Lambda;/g, 'Λ');
str = str.replace(/&Mu;/g, 'Μ');
str = str.replace(/&Nu;/g, 'Ν');
str = str.replace(/&Xi;/g, 'Ν');
str = str.replace(/&Omicron;/g, 'Ο');
str = str.replace(/&Pi;/g, 'Π');
str = str.replace(/&Rho;/g, 'Ρ');
str = str.replace(/&Sigma;/g, 'Σ');
str = str.replace(/&Tau;/g, 'Τ');
str = str.replace(/&Upsilon;/g, 'Υ');
str = str.replace(/&Phi;/g, 'Φ');
str = str.replace(/&Chi;/g, 'Χ');
str = str.replace(/&Psi;/g, 'Ψ');
str = str.replace(/&Omega;/g, 'Ω');
str = str.replace(/&alpha;/g, 'α');
str = str.replace(/&beta;/g, 'β');
str = str.replace(/&gamma;/g, 'γ');
str = str.replace(/&delta;/g, 'δ');
str = str.replace(/&epsilon;/g, 'ε');
str = str.replace(/&zeta;/g, 'ζ');
str = str.replace(/&eta;/g, 'η');
str = str.replace(/&theta;/g, 'θ');
str = str.replace(/&iota;/g, 'ι');
str = str.replace(/&kappa;/g, 'κ');
str = str.replace(/&lambda;/g, 'λ');
str = str.replace(/&mu;/g, 'μ');
str = str.replace(/&nu;/g, 'ν');
str = str.replace(/&xi;/g, 'ξ');
str = str.replace(/&omicron;/g, 'ο');
str = str.replace(/&pi;/g, 'π');
str = str.replace(/&rho;/g, 'ρ');
str = str.replace(/&sigmaf;/g, 'ς');
str = str.replace(/&sigma;/g, 'σ');
str = str.replace(/&tau;/g, 'τ');
str = str.replace(/&upsilon;/g, 'υ');
str = str.replace(/&phi;/g, 'φ');
str = str.replace(/&chi;/g, 'χ');
str = str.replace(/&psi;/g, 'ψ');
str = str.replace(/&omega;/g, 'ω');
str = str.replace(/&thetasym;/g, 'ϑ');
str = str.replace(/&upsih;/g, 'ϒ');
str = str.replace(/&piv;/g, 'ϖ');
str = str.replace(/&middot;/g, '·');
return str;
}
//
function strcharacterDiscode(str) {
// 加入常用解析
str = str.replace(/&nbsp;/g, ' ');
str = str.replace(/&quot;/g, "'");
str = str.replace(/&amp;/g, '&');
// str = str.replace(/&lt;/g, '‹');
// str = str.replace(/&gt;/g, '›');
str = str.replace(/&lt;/g, '<');
str = str.replace(/&gt;/g, '>');
str = str.replace(/&#8226;/g, '•');
return str;
}
// HTML 支持的其他实体
function strOtherDiscode(str) {
str = str.replace(/&OElig;/g, 'Œ');
str = str.replace(/&oelig;/g, 'œ');
str = str.replace(/&Scaron;/g, 'Š');
str = str.replace(/&scaron;/g, 'š');
str = str.replace(/&Yuml;/g, 'Ÿ');
str = str.replace(/&fnof;/g, 'ƒ');
str = str.replace(/&circ;/g, 'ˆ');
str = str.replace(/&tilde;/g, '˜');
str = str.replace(/&ensp;/g, '');
str = str.replace(/&emsp;/g, '');
str = str.replace(/&thinsp;/g, '');
str = str.replace(/&zwnj;/g, '');
str = str.replace(/&zwj;/g, '');
str = str.replace(/&lrm;/g, '');
str = str.replace(/&rlm;/g, '');
str = str.replace(/&ndash;/g, '–');
str = str.replace(/&mdash;/g, '—');
str = str.replace(/&lsquo;/g, '‘');
str = str.replace(/&rsquo;/g, '’');
str = str.replace(/&sbquo;/g, '‚');
str = str.replace(/&ldquo;/g, '“');
str = str.replace(/&rdquo;/g, '”');
str = str.replace(/&bdquo;/g, '„');
str = str.replace(/&dagger;/g, '†');
str = str.replace(/&Dagger;/g, '‡');
str = str.replace(/&bull;/g, '•');
str = str.replace(/&hellip;/g, '…');
str = str.replace(/&permil;/g, '‰');
str = str.replace(/&prime;/g, '′');
str = str.replace(/&Prime;/g, '″');
str = str.replace(/&lsaquo;/g, '‹');
str = str.replace(/&rsaquo;/g, '›');
str = str.replace(/&oline;/g, '‾');
str = str.replace(/&euro;/g, '€');
str = str.replace(/&trade;/g, '™');
str = str.replace(/&larr;/g, '←');
str = str.replace(/&uarr;/g, '↑');
str = str.replace(/&rarr;/g, '→');
str = str.replace(/&darr;/g, '↓');
str = str.replace(/&harr;/g, '↔');
str = str.replace(/&crarr;/g, '↵');
str = str.replace(/&lceil;/g, '⌈');
str = str.replace(/&rceil;/g, '⌉');
str = str.replace(/&lfloor;/g, '⌊');
str = str.replace(/&rfloor;/g, '⌋');
str = str.replace(/&loz;/g, '◊');
str = str.replace(/&spades;/g, '♠');
str = str.replace(/&clubs;/g, '♣');
str = str.replace(/&hearts;/g, '♥');
str = str.replace(/&diams;/g, '♦');
str = str.replace(/&#39;/g, "'");
return str;
}
function strDiscode(str) {
str = strNumDiscode(str);
str = strGreeceDiscode(str);
str = strcharacterDiscode(str);
str = strOtherDiscode(str);
return str;
}
function urlToHttpUrl(url, rep) {
const patt1 = new RegExp('^//');
const result = patt1.test(url);
if (result) {
url = `${rep}:${url}`;
}
return url;
}
export default {
strDiscode,
urlToHttpUrl,
};

257
examples/uniapp-one/components/mpvue-wxparse/wxParse.css

@ -0,0 +1,257 @@
/**
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
.wxParse {
width: 100%;
font-family: Helvetica, sans-serif;
font-size: 28rpx;
color: #666;
line-height: 1.8;
}
view {
word-break: hyphenate;
}
.wxParse .inline {
display: inline;
margin: 0;
padding: 0;
}
/*//标题 */
.wxParse .div {
margin: 0;
padding: 0;
}
.wxParse .h1 {
font-size: 2em;
margin: 0.67em 0;
}
.wxParse .h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
.wxParse .h3 {
font-size: 1.17em;
margin: 1em 0;
}
.wxParse .h4 {
margin: 1.33em 0;
}
.wxParse .h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
.wxParse .h6 {
font-size: 0.67em;
margin: 2.33em 0;
}
.wxParse .h1,
.wxParse .h2,
.wxParse .h3,
.wxParse .h4,
.wxParse .h5,
.wxParse .h6,
.wxParse .b,
.wxParse .strong {
font-weight: bolder;
}
.wxParse .p {
margin: 1em 0;
}
.wxParse .i,
.wxParse .cite,
.wxParse .em,
.wxParse .var,
.wxParse .address {
font-style: italic;
}
.wxParse .pre,
.wxParse .tt,
.wxParse .code,
.wxParse .kbd,
.wxParse .samp {
font-family: monospace;
}
.wxParse .pre {
background: #f5f5f5;
padding: 16rpx;
white-space: pre-wrap;
}
.wxParse .big {
font-size: 1.17em;
}
.wxParse .small,
.wxParse .sub,
.wxParse .sup {
font-size: 0.83em;
}
.wxParse .sub {
vertical-align: sub;
}
.wxParse .sup {
vertical-align: super;
}
.wxParse .s,
.wxParse .strike,
.wxParse .del {
text-decoration: line-through;
}
/*wxparse-自定义个性化的css样式*/
/*增加video的css样式*/
.wxParse .strong,
.wxParse .s {
display: inline;
}
.wxParse .a {
color: deepskyblue;
word-break: break-all;
overflow: auto;
}
.wxParse .video {
text-align: center;
margin: 20rpx 0;
}
.wxParse .video-video {
width: 100%;
}
.wxParse .img {
width: 0;
height: 0;
max-width: 100%;
overflow: hidden;
}
.wxParse .blockquote {
margin: 10rpx 0;
padding: 20rpx 0 20rpx 20rpx;
font-family: Courier, Calibri, "宋体";
background: #f5f5f5;
border-left: 6rpx solid #dbdbdb;
}
.wxParse .blockquote .p {
margin: 0;
}
.wxParse .code {
display: inline;
background: #f5f5f5;
}
.wxParse .ul {
margin: 20rpx 10rpx;
}
.wxParse .li,
.wxParse .li-inner {
display: flex;
align-items: baseline;
margin: 10rpx 0;
}
.wxParse .li-text {
display: flex;
align-items: center;
line-height: 40rpx;
}
.wxParse .li-circle {
display: inline-flex;
width: 10rpx;
height: 10rpx;
background-color: #333;
margin-right: 10rpx;
border-radius: 50%;
position: relative;
top: -5rpx;
}
.wxParse .li-square {
display: inline-flex;
width: 10rpx;
height: 10rpx;
background-color: #333;
margin-right: 10rpx;
}
.wxParse .li-ring {
display: inline-flex;
width: 10rpx;
height: 10rpx;
border: 2rpx solid #333;
border-radius: 50%;
background-color: #fff;
margin-right: 10rpx;
}
.wxParse .table {
width: 100%;
border-top: 2rpx solid #e0e0e0;
}
.wxParse .thead,.wxParse .tfoot,.wxParse .tr {
display: flex;
flex-direction: row;
}
.wxParse .th,.wxParse .td {
display: flex;
width: 1160rpx;
overflow: auto;
}
.wxParse .u {
text-decoration: underline;
}
.wxParse .hide {
display: none;
}
.wxParseText {
align-items: center;
}
.wxParse .tr {
width:100%;
display: flex;
border-right: 2rpx solid #e0e0e0;
border-bottom: 2rpx solid #e0e0e0;
}
.wxParse .th,
.wxParse .td {
flex: 1;
padding: 10rpx;
border-left: 2rpx solid #e0e0e0;
word-break: break-all;
}
.wxParse .td:last {
border-top: 2rpx solid #e0e0e0;
}
.wxParse .th {
background: #f0f0f0;
border-top: 2rpx solid #e0e0e0;
}
.wxParse .del {
display: inline;
}
.wxParse .figure {
overflow: hidden;
}

65
examples/uniapp-one/components/mpvue-wxparse/wxParse.vue

@ -0,0 +1,65 @@
<!--**
* author: F-loat <chaimaoyuan@foxmail.com>
*
* github地址: https://github.com/F-loat/mpvue-wxParse
*
* for: Mpvue框架下 微信小程序富文本解析
*/-->
<template>
<!--基础元素-->
<div class="wxParse">
<block v-for="node of wxParseData.nodes" :key="node.index">
<wxParseTemplate :node="node" />
</block>
</div>
</template>
<script>
import HtmlToJson from './libs/html2json';
import wxParseTemplate from './components/wxParseTemplate0';
export default {
name: 'wxParse',
props: {
content: {
type: String,
default() {
return '<div class="color:red;">数据不能为空</div>';
},
},
image: {
type: String,
default() {
return {
mode: 'aspectFit',
padding: 0,
lazyLoad: false,
};
},
},
debug: {
type: Boolean,
default() {
return false;
},
},
},
components: {
wxParseTemplate,
},
computed: {
wxParseData() {
const { content, image, debug } = this;
const transData = HtmlToJson(content, image, debug);
if (debug) console.log(JSON.stringify(transData, null, ' '));
return transData;
},
},
};
</script>
<style>
@import url("./wxParse.css");
</style>

97
examples/uniapp-one/components/questionList.vue

@ -0,0 +1,97 @@
<template>
<view class="read-item">
<view class="dot"></view>
<view class="content">
<view class="title">
<text>{{content.question_title}}</text>
</view>
<view class="guide">
<text>{{content.answer_content}}</text>
</view>
<view class="author" v-if="content.author_list && content.author_list.length">
<text> {{content.author_list[0].user_name}}</text>
</view>
</view>
<view class="date">{{content.question_makettime}}</view>
</view>
</template>
<script>
export default {
props: {
item: Object
},
computed: {
content() {
const item = this.item
item.question_makettime = item.question_makettime.substr(5, 5).split('-').join('月') + '日'
return item
}
}
}
</script>
<style scoped>
.read-item {
width: 100%;
height: 300rpx;
position: relative;
display: flex;
justify-content: space-between;
text-align: left;
}
.date {
width: 160rpx;
text-indent: 1em;
white-space: nowrap;
line-height: 70rpx;
}
.title {
line-height: 80rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-size: 36rpx;
}
.guide {
line-height: 38rpx;
height: 76rpx;
overflow: hidden;
}
.author {
text-align: right;
margin-right: 20rpx;
}
.content {
width: 540rpx;
height: 246rpx;
box-sizing: border-box;
border-radius: 10rpx;
background: linear-gradient(to bottom right, #9653fe, #507fff);
color: #fff;
position: relative;
margin-left: 20rpx;
padding: 2rpx 12rpx 0;
}
.content::before {
content: '';
display: block;
width: 0;
height: 0;
border-width: 15rpx 12rpx;
border-style: solid;
border-color: transparent transparent transparent #6c6dfe;
position: absolute;
top: 20rpx;
right: -20rpx;
}
.dot {
width: 18rpx;
height: 18rpx;
background-color: rgba(108, 109, 254, .6);
position: absolute;
top: 26rpx;
right: 150rpx;
border-radius: 50%;
}
</style>

98
examples/uniapp-one/components/readList.vue

@ -0,0 +1,98 @@
<template>
<view class="read-item">
<view class="dot"></view>
<view class="date">{{content.hp_makettime}}</view>
<view class="content">
<view class="title">
<text>{{content.hp_title}}</text>
</view>
<view class="guide">
<text>{{content.guide_word}}</text>
</view>
<view class="author" v-if="content.author && content.author.length">
<text> {{content.author[0].user_name}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: Object
},
computed: {
content() {
const item = this.item
item.hp_makettime = item.hp_makettime.substr(5, 5).split('-').join('月') + '日'
return item
}
}
}
</script>
<style scoped>
.read-item {
width: 100%;
height: 300rpx;
position: relative;
display: flex;
justify-content: space-between;
text-align: left;
}
.date {
width: 160rpx;
text-indent: 1em;
white-space: nowrap;
line-height: 70rpx;
}
.title {
line-height: 80rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-size: 36rpx;
}
.guide {
line-height: 38rpx;
height: 76rpx;
overflow: hidden;
}
.author {
text-align: right;
margin-right: 20rpx;
}
.content {
width: 540rpx;
height: 246rpx;
box-sizing: border-box;
border-radius: 10rpx;
/* background-color: #42adda; */
background: linear-gradient(to bottom right, #9653fe, #507fff);
color: #fff;
position: relative;
margin-right: 20rpx;
padding: 2rpx 12rpx 0;
}
.content::before {
content: '';
display: block;
width: 0;
height: 0;
border-width: 15rpx 12rpx;
border-style: solid;
border-color: transparent #9653fe transparent transparent;
position: absolute;
top: 20rpx;
left: -20rpx;
}
.dot {
width: 18rpx;
height: 18rpx;
background-color: rgba(150, 83, 254, .6);
position: absolute;
top: 26rpx;
left: 150rpx;
border-radius: 50%;
}
</style>

13
examples/uniapp-one/main.js

@ -0,0 +1,13 @@
import Vue from 'vue'
import App from './App'
import store from '@/store'
Vue.config.productionTip = false
Vue.prototype.$store = store
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()

53
examples/uniapp-one/manifest.json

@ -0,0 +1,53 @@
{
"name" : "uni-one",
"appid" : "__UNI__04F77E3",
"description" : "A uni-app project",
"versionName" : "1.0.0",
"versionCode" : "100",
"app-plus" : {/* App */
"modules" : {/* */
},
"distribute" : {/* */
"android" : {/* android */
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios" : {/* ios */
},
"sdkConfigs" : {/* SDK */
}
}
},
"quickapp" : {/* */
},
"mp-weixin" : {/* */
"appid" : ""
}
}

79
examples/uniapp-one/pages.json

@ -0,0 +1,79 @@
{
"pages": [
{
"path": "pages/home/main",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/read/main",
"style": {
"navigationBarTitleText": "文章&问答"
}
},
{
"path": "pages/read/essay/main"
},
{
"path": "pages/read/question/main"
},
{
"path": "pages/movie/main",
"style": {
"navigationBarTitleText": "影评"
}
},
{
"path": "pages/movie/detail/main"
},
{
"path": "pages/daily/main",
"style": {
"navigationBarTitleText": "日报"
}
},
{
"path": "pages/daily/detail/main",
"style": {
"navigationBarTitleText": "日报"
}
}
],
"globalStyle": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "fafafa",
"navigationBarTitleText": "一个",
"navigationBarTextStyle": "black"
},
"tabBar": {
"color": "#130f13",
"selectedColor": "#0f0f0f",
"list": [
{
"pagePath": "pages/home/main",
"text": "ONE",
"iconPath": "static/icon/home.png",
"selectedIconPath": "static/icon/home-active.png"
},
{
"pagePath": "pages/read/main",
"text": "READ",
"iconPath": "static/icon/read.png",
"selectedIconPath": "static/icon/read-active.png"
},
{
"pagePath": "pages/movie/main",
"text": "MOVIE",
"iconPath": "static/icon/movie.png",
"selectedIconPath": "static/icon/movie-active.png"
},
{
"pagePath": "pages/daily/main",
"text": "DAILY",
"iconPath": "static/icon/daily.png",
"selectedIconPath": "static/icon/daily-active.png"
}
]
}
}

145
examples/uniapp-one/pages/daily/detail/main.vue

@ -0,0 +1,145 @@
<style scoped>
.cover {
width: 300rpx;
height: 300rpx;
margin: 20rpx auto 0;
border-radius: 16rpx;
box-shadow: 10rpx 10rpx 20rpx rgba(0, 0, 0, .2);
}
.control {
width: 80rpx;
height: 80rpx;
background-color: rgba(0, 0, 0, .4);
position: absolute;
top: 50%;
left: 50%;
border-radius: 50%;
margin: -60rpx 0 0 -40rpx;
}
.feeds_cover {
width: 100%;
height: 400rpx;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
.control img {
width: 32rpx;
height: 32rpx;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.title {
font-size: 30rpx;
font-weight: bold;
height: 96rpx;
line-height: 48rpx;
margin-top: 40rpx;
text-align: center;
}
</style>
<style>
.meta.div {
height: 120rpx;
padding-left: 40rpx;
position: relative;
}
.meta.div::before {
content: '';
display: block;
position: absolute;
top: 12rpx;
left: 10rpx;
width: 0;
height: 0;
border-width: 12rpx 16rpx;
border-style: solid;
border-color: transparent transparent transparent #000;
animation: circle 1s infinite;
transform-origin: 25% 50%;
}
.meta.div::after {
content: '';
display: block;
position: absolute;
top: 12rpx;
left: 10rpx;
width: 0;
height: 0;
border-width: 12rpx 16rpx;
border-style: solid;
border-color: transparent transparent transparent #000;
animation: fadeIn 1s infinite;
}
.meta.div .avatar {
display: none;
}
.view-more.div {
display: none;
}
@keyframes circle {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(16rpx);
opacity: 0;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
<template>
<div class="article-container">
<div class="title">{{title}}</div>
<wx-parse :content="body"></wx-parse>
</div>
</template>
<script>
import API from '@/utils/api'
import wxParse from '../../../components/mpvue-wxparse/wxParse.vue'
export default {
data() {
return {
loaded: false,
isPlay: false,
audioContext: null,
body: '',
title: ''
}
},
components: {
wxParse
},
onLoad(query) {
const id = query.id
if (!id) console.log('error coured no id find.')
this.getDetail(id)
},
methods: {
async getDetail(id) {
const data = await API.getZhDtl(id)
this.body = data.body
this.title = data.title
}
}
}
</script>
<style scoped>
</style>

141
examples/uniapp-one/pages/daily/main.vue

@ -0,0 +1,141 @@
<style scoped>
li {
min-height: 160rpx;
display: flex;
align-items: center;
border-bottom: 2rpx solid #fafbff;
padding: 0 20rpx;
}
li:active {
background-color: #f15549;
padding-left: 20rpx;
}
li:active .title, li:active .subtitle {
color: #fff;
}
li img {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
display: block;
}
.desc {
width: 480rpx;
text-align: left;
line-height: 48rpx;
padding-left: 40rpx;
}
.title {
color: #7f7f7f;
font-size: 32rpx;
}
.play {
margin-left: 40rpx;
}
.play img {
width: 40rpx;
height: 40rpx;
}
.slide-image {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.item-title {
position: absolute;
width: 100%;
box-sizing: border-box;
padding: 0 40rpx 60rpx;
font-size: 36rpx;
text-align: left;
color: #fff;
left: 0;
bottom: 0;
z-index: 11;
}
swiper {
width: 100%;
height: 400rpx;
position: fixed;
top: 0;
left: 0;
}
swiper-item {
position: relative;
}
.layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, .3));
}
.list {
margin-top: 400rpx;
}
</style>
<template>
<div class="container">
<swiper :indicator-dots="true" :autoplay="true" :circular="true">
<block v-for="v in top_stories" :key="v.id">
<swiper-item @tap="toDtl(v.id)">
<image :src="v.image" class="slide-image" mode="center"/>
<div class="item-title">{{v.title}}</div>
<div class="layer"></div>
</swiper-item>
</block>
</swiper>
<ul class="list">
<li v-for="v in all_stories" :key="v.id" @tap="toDtl(v.id)">
<img :src="v.image" alt="cover">
<div class="desc">
<div class="title">
{{v.title}}
</div>
</div>
<div class="play">
<img src="/static/assert/arrow-right.png" alt="play">
</div>
</li>
</ul>
</div>
</template>
<script>
import API from '@/utils/api'
export default {
data() {
return {
top_stories: [],
stories: [],
innerAudioContext: ''
}
},
mounted() {
this.getDailyList()
},
computed: {
all_stories() {
return this.stories.map(v => ({
...v,
image: v.images[0]
}))
}
},
methods: {
async getDailyList() {
const res = await API.getZhList()
console.log(res.top_stories)
this.top_stories = res.top_stories
this.stories = res.stories
},
toDtl(id) {
wx.navigateTo({ url: '/pages/daily/detail/main?id=' + id })
}
}
}
</script>

65
examples/uniapp-one/pages/home/main.vue

@ -0,0 +1,65 @@
<template>
<div class="container">
<image class="cover" :src="data.hp_img_url" mode="widthFix" />
<view class="cover-author">
<text class="gray">{{data.hp_author}}</text>
</view>
<view class="content">
<text>{{content}}</text>
</view>
<view class="content-author">
<text class="gray">{{data.text_authors}}</text>
</view>
<weather :weather="weather" v-if="weather.status === 'ok'"></weather>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import weather from './weather'
export default {
mounted() {
this.initPage()
},
components: {
weather
},
computed: {
...mapState('home', ['data']),
...mapState('weather', ['weather']),
content() {
return this.data.hp_content.split('by')[0]
}
},
methods: {
...mapActions('home', ['getNewIds', 'getHomeData']),
async initPage() {
await this.getNewIds()
await this.getHomeData()
}
}
}
</script>
<style scoped>
.cover {
width: 100%;
}
.cover-author {
width: 100%;
height: 100rpx;
line-height: 100rpx;
margin-bottom: 30rpx;
}
.content {
width: 80%;
margin: 0 auto;
line-height: 58rpx;
text-align: left;
}
.content-author {
height: 100rpx;
line-height: 100rpx;
font-size: 20rpx;
}
</style>

56
examples/uniapp-one/pages/home/weather.vue

@ -0,0 +1,56 @@
<template>
<div class="weather">
<div class="date">{{day}}</div>
<div class="location">
{{weather.basic.location}}
</div>
<img :src="'https://petrify.oss-cn-beijing.aliyuncs.com/weather/' + weather.now.cond_code + '.png'" alt="">
<div class="cond-text">{{weather.now.cond_txt}}</div>
<div class="tmp"><span>{{weather.now.tmp}}°C</span></div>
<div class="fl">体感<span>{{weather.now.fl}}°C</span></div>
</div>
</template>
<script>
const DAY_LIST = ['Sun', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat']
export default {
props: {
weather: Object
},
computed: {
day() {
const day = new Date().getDay()
return DAY_LIST[day]
}
}
}
</script>
<style scoped>
.weather {
height: 170rpx;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
font-size: 36rpx;
justify-content: space-around;
}
.date {
color: #ecc88e;
font-size: 48rpx;
font-weight: 700;
padding: 0 20rpx;
}
.location {
color: #b4b0ad;
}
img {
width: 80rpx;
height: 80rpx;
}
.tmp span, .fl span {
color: #52b9b6;
}
</style>

38
examples/uniapp-one/pages/movie/detail/main.vue

@ -0,0 +1,38 @@
<template>
<block>
<v-article
:title="currentMovie.title"
:user_name="currentMovie.user ? currentMovie.user.user_name : ''"
:content="currentMovie.content || ''"
:summary="currentMovie.summary || ''"
></v-article>
</block>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import article from '@/components/article'
export default {
onLoad(query) {
this.clearMovieDetail()
const { id } = query
this.initPage(id)
},
components: {
'v-article': article
},
computed: {
...mapState('movie', ['currentMovie'])
},
methods: {
...mapActions('movie', ['getMovieDetail', 'clearMovieDetail']),
async initPage(id) {
await this.getMovieDetail(id)
}
}
}
</script>
<style scoped>
</style>

51
examples/uniapp-one/pages/movie/main.vue

@ -0,0 +1,51 @@
<template>
<div class="container">
<navigator
v-for="v in movies"
:key="v.item_id"
:url="'/pages/movie/detail/main?id=' + v.item_id"
class="item"
>
<movie-detail :movie="v"></movie-detail>
</navigator>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import movieDetail from '@/components/movieItem'
export default {
mounted () {
this.initPage()
},
components: {
movieDetail
},
computed: {
...mapState('movie', ['movies'])
},
methods: {
...mapActions('movie', ['getMovieList']),
async initPage() {
await this.getMovieList()
}
}
}
</script>
<style scoped>
navigator {
width: 100%;
}
.item {
width: 100%;
height: 170rpx;
}
.item:nth-child(odd) {
background-color: #e5e4df;
}
.item:nth-child(even) {
background-color: #eae9e4;
}
</style>

34
examples/uniapp-one/pages/read/essay/main.vue

@ -0,0 +1,34 @@
<template>
<block>
<v-article
:title="readContent.essay.hp_title"
:user_name="readContent.essay.hp_author"
:content="readContent.essay.hp_content || ''"
></v-article>
</block>
</template>
<script>
import article from '@/components/article'
import { mapState, mapActions } from 'vuex'
export default {
onLoad(params) {
this.clearReadContent({type: 'essay'})
const { id } = params
this.getReadContent({ type: 'essay', id })
},
components: {
'v-article': article
},
computed: {
...mapState('read', ['readContent'])
},
methods: {
...mapActions('read', ['getReadContent', 'clearReadContent'])
}
}
</script>
<style scoped>
</style>

68
examples/uniapp-one/pages/read/main.vue

@ -0,0 +1,68 @@
<template>
<div class="container">
<view class="mode-title" v-if="readList.essay && readList.essay.length">
<view class="mode-title-word">
<text>阅读</text>
</view>
</view>
<navigator v-for="v in readList.essay" :key="v.content_id" :url="'/pages/read/essay/main?id=' + v.content_id">
<read-list :item="v"></read-list>
</navigator>
<view class="mode-title" v-if="readList.question && readList.question.length">
<view class="mode-title-word">
<text>问答</text>
</view>
</view>
<navigator v-for="v in readList.question" :key="v.question_id" :url="'/pages/read/question/main?id=' + v.question_id">
<question-list :item="v"></question-list>
</navigator>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import readList from '@/components/readList'
import questionList from '@/components/questionList'
export default {
mounted() {
this.getReadList()
},
components: {
readList,
questionList
},
computed: {
...mapState('read', ['readList'])
},
methods: {
...mapActions('read', ['getReadList'])
}
}
</script>
<style scoped>
.mode-title {
height: 80rpx;
line-height: 80rpx;
position: relative;
margin-bottom: 20rpx;
}
.mode-title .mode-title-word {
width: 120rpx;
margin: 0 auto;
font-size: 36rpx;
background-color: #fff;
}
.mode-title:before {
content: '';
display: block;
width: 80%;
height: 2rpx;
background-color: #b4b4b5;
position: absolute;
top: 50%;
left: 10%;
z-index: -1;
}
</style>

92
examples/uniapp-one/pages/read/question/main.vue

@ -0,0 +1,92 @@
<template>
<div class="wrapper">
<view class="title">
<text>{{detail.question_title}}</text>
</view>
<view class="ask">
<view class="asker" v-if="detail.answerer">
<text>{{detail.asker.user_name}}</text>
</view>
<view class="asker" v-else>
<text>网友问</text>
</view>
<wx-parse :content="detail.question_content || ''"></wx-parse>
</view>
<view class="divider"></view>
<view class="answer">
<view class="answerer" v-if="detail.answerer">
<text>{{detail.answerer.user_name}}</text>
</view>
<view class="answerer" v-else>
<text>网友答</text>
</view>
<wx-parse :content="detail.answer_content || ''"></wx-parse>
</view>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import wxParse from '../../../components/mpvue-wxparse/wxParse.vue'
export default {
onLoad(params) {
this.clearReadContent({type: 'question'})
const { id } = params
this.getReadContent({ type: 'question', id })
},
components: {
wxParse
},
computed: {
...mapState('read', ['readContent']),
detail() {
return this.readContent.question
}
},
methods: {
...mapActions('read', ['getReadContent', 'clearReadContent'])
}
}
</script>
<style scoped>
.title {
font-size: 32rpx;
overflow: hidden;
text-align: center;
padding: .8em;
font-weight: bold;
}
.asker, .answerer {
font-size: 30rpx;
padding-left: 1em;
height: 60rpx;
}
.divider {
width: 90%;
margin: 15rpx auto;
position: relative;
height: 2rpx;
background-color: #b4b4b4;
}
.divider::before {
content: '';
width: 50rpx;
height: 2rpx;
background-color: #fff;
position: absolute;
top: 0;
left: calc(50% - 25rpx);
}
.divider::after {
content: '';
display: block;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background-color: #b4b4b4;
position: absolute;
top: -4rpx;
left: calc(50% - 5rpx);
}
</style>

BIN
examples/uniapp-one/static/assert/arrow-right.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
examples/uniapp-one/static/assert/music.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
examples/uniapp-one/static/assert/pause.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
examples/uniapp-one/static/assert/play.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
examples/uniapp-one/static/icon/daily-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
examples/uniapp-one/static/icon/daily.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
examples/uniapp-one/static/icon/home-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
examples/uniapp-one/static/icon/home.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
examples/uniapp-one/static/icon/movie-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
examples/uniapp-one/static/icon/movie.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
examples/uniapp-one/static/icon/read-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
examples/uniapp-one/static/icon/read.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

33
examples/uniapp-one/store/index.js

@ -0,0 +1,33 @@
import Vue from 'vue'
import Vuex from 'vuex'
import home from './modules/home'
import movie from './modules/movie'
import read from './modules/read'
import weather from './modules/weather'
// import music from './modules/music'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
home: {
namespaced: true,
...home
},
movie: {
namespaced: true,
...movie
},
read: {
namespaced: true,
...read
},
weather: {
namespaced: true,
...weather
}
}
})
export default store

38
examples/uniapp-one/store/modules/home.js

@ -0,0 +1,38 @@
import { CHANGE_HOME_DATA, STORE_ID_LIST } from './../mutations_type'
import API from '@/utils/api'
const state = {
ids: [],
data: {
hp_content: '',
hp_img_url: '',
hp_author: '',
text_authors: ''
}
}
const mutations = {
[CHANGE_HOME_DATA](state, payload) {
state.data = payload.data
},
[STORE_ID_LIST](state, payload) {
state.ids = payload.ids
}
}
const actions = {
async getNewIds({ commit }) {
const { data } = await API.getNewIds()
commit(STORE_ID_LIST, { ids: data })
},
async getHomeData({ commit, state }) {
const { data } = await API.getHomeData(state.ids[0])
commit(CHANGE_HOME_DATA, { data })
}
}
export default {
state,
mutations,
actions
}

40
examples/uniapp-one/store/modules/movie.js

@ -0,0 +1,40 @@
import { CHANGE_MOVIE_LIST, CHANGE_CURRENT_MOVIE } from './../mutations_type'
import API from '@/utils/api'
const state = {
movies: [],
currentMovie: {}
}
const mutations = {
[CHANGE_MOVIE_LIST](state, payload) {
state.movies = payload.movies
},
[CHANGE_CURRENT_MOVIE](state, payload) {
state.currentMovie = payload.data
}
}
const actions = {
async getMovieList({ commit }) {
const { data } = await API.getMovieList()
commit(CHANGE_MOVIE_LIST, { movies: data })
},
async getMovieDetail({ commit, state }, id) {
const { data: { data } } = await API.getMovieDetail(id)
commit(CHANGE_CURRENT_MOVIE, { data: data[0] })
},
async getMovieArticleDetail({ commit, state }, id) {
const { data: { data } } = await API.getMovieArticleDetail(id)
commit(CHANGE_CURRENT_MOVIE, { data: data[0] })
},
clearMovieDetail({ commit }) {
commit(CHANGE_CURRENT_MOVIE, { data: {} })
}
}
export default {
state,
mutations,
actions
}

47
examples/uniapp-one/store/modules/read.js

@ -0,0 +1,47 @@
import API from '@/utils/api'
import { CHANGE_CURRENT_READ, CHANGE_READ_LIST } from './../mutations_type'
const state = {
readList: {
essay: [],
question: [],
serial: []
},
readContent: {
essay: {},
question: {}
}
}
const mutations = {
[CHANGE_READ_LIST] (state, payload) {
state.readList = payload.data
},
[CHANGE_CURRENT_READ] (state, payload) {
state.readContent[payload.type] = payload.data
}
}
const actions = {
async getReadList({ commit, state }) {
const { data } = await API.getReadList()
commit(CHANGE_READ_LIST, { data })
},
async getReadContent({ commit, state }, { type, id }) {
const { data } = await API.getReadDetail(type, id)
commit(CHANGE_CURRENT_READ, { type, data })
},
async clearReadContent({ commit, state }, { type }) {
commit(CHANGE_CURRENT_READ, { type, data: {} })
}
// async getReadComment({ commit, state }, id) {
// // const { data } = await API.getReadComment(id)
// // commit(CHANGE_CURRENT_READ, { data })
// }
}
export default {
state,
mutations,
actions
}

38
examples/uniapp-one/store/modules/weather.js

@ -0,0 +1,38 @@
import API from '@/utils/api'
import { SET_LOCATION, SET_WEATHER } from '../mutations_type'
const state = {
location: {
latitude: '',
longitude: ''
},
weather: {
basic: {},
now: {},
update: {},
status: ''
}
}
const mutations = {
[SET_LOCATION] (state, payload) {
state.location = payload.location
},
[SET_WEATHER] (state, payload) {
state.weather = payload.weather
}
}
const actions = {
async getWeather({ state, commit }) {
console.log('getWeather')
const location = state.location
const data = await API.getWeather(`${location.latitude},${location.longitude}`)
commit(SET_WEATHER, { weather: data.result })
}
}
export default {
state,
mutations,
actions
}

14
examples/uniapp-one/store/mutations_type.js

@ -0,0 +1,14 @@
export const CHANGE_HOME_DATA = 'CHANGE_HOME_DATA'
export const STORE_ID_LIST = 'STORE_ID_LIST'
export const CHANGE_MOVIE_LIST = 'CHANGE_MOVIE_LIST'
export const CHANGE_CURRENT_MOVIE = 'CHANGE_CURRENT_MOVIE'
export const CHANGE_READ_LIST = 'CHANGE_READ_LIST'
export const CHANGE_CURRENT_READ = 'CHANGE_CURRENT_READ'
export const CHANGE_MUSIC_LIST = 'CHANGE_MUSIC_LIST'
export const CHANGE_CURRENT_MUSIC = 'CHANGE_CURRENT_MUSIC'
export const SET_LOCATION = 'SET_LOCATION'
export const SET_WEATHER = 'SET_WEATHER'

29
examples/uniapp-one/utils/api.js

@ -0,0 +1,29 @@
import request from './request'
const baseURL = `https://petrify.cc`
// const baseURL = 'http://192.168.29.238:7001'
request.config.baseURL = baseURL
const dailyRequest = (id) => request.post('/v1/daily', {
url: `/api/4/news/${id}`
})
const api = {
// picture
getNewIds: () => request.get(`/v1/one?${encodeURI('url=/api/hp/idlist/0?version=3.5.0&platform=android')}`),
getHomeData: (id) => request.get(`/v1/one?${encodeURI('url=/api/hp/detail/' + id + '?version=3.5.0&platform=android')}`),
// read
getReadList: () => request.get(`/v1/one?${encodeURI('url=/api/reading/index/?version=3.5.0&platform=android')}`),
getReadDetail: (type, id) => request.get(`/v1/one?${encodeURI('url=/api/' + type + '/' + id + '?version=3.5.0&platform=android')}`),
getReadComment: (id) => request.get(`/v1/one?${encodeURI('url=/api/comment/praiseandtime/essay/' + id + '/0?version=3.5.0&platform=android')}`),
getMovieList: () => request.post('/v1/two', {
url: '/api/channel/movie/more/0?channel=wdj&version=4.0.2&uuid=ffffffff-a90e-706a-63f7-ccf973aae5ee&platform=android'
}),
getMovieDetail: (id) => request.get(`/v1/one?${encodeURI('url=/api/movie/' + id + '/story/1/0?version=3.5.0&platform=android')}`),
getWeather: (location) => request.get(`/v1/weather?location=${location}`),
// 知乎日报
getZhList: () => dailyRequest('latest'),
getZhDtl: (id) => dailyRequest(id)
}
export default api

29
examples/uniapp-one/utils/request.js

@ -0,0 +1,29 @@
import Fly from 'flyio/dist/npm/wx'
const request = new Fly()
const errorPrompt = (err) => {
wx.showToast({
title: err.message || 'fetch data error.',
icon: 'none'
})
}
request.interceptors.request.use((request) => {
wx.showNavigationBarLoading()
return request
})
request.interceptors.response.use((response, promise) => {
wx.hideNavigationBarLoading()
// if (!(response && response.data && response.data.res === 0)) {
// errorPrompt(response)
// }
return promise.resolve(response.data)
}, (err, promise) => {
wx.hideNavigationBarLoading()
errorPrompt(err)
return promise.reject(err)
})
export default request

25
examples/wxcomponents-template/App.vue

@ -0,0 +1,25 @@
<script>
export default {
onLaunch: function () {
console.log('App Launch')
},
onShow: function () {
console.log('App Show')
},
onHide: function () {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
page {
min-height: 100%;
background: #ECECEC;
}
.title{
padding: 10px;
text-align: center;
}
</style>

12
examples/wxcomponents-template/README.md

@ -0,0 +1,12 @@
# 小程序自定义组件使用示例
## 注意事项
* 小程序自定义组件需放在wxcomponents目录
* 使用的组件需添加到pages.json文件内
* 原组件内事件名称需修改为驼峰命名,如:
```js
// wxcomponents/vant-weapp/dist/nav-bar/index.js
this.$emit('click-left');
// 改为
this.$emit('clickLeft');
```

11
examples/wxcomponents-template/main.js

@ -0,0 +1,11 @@
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()

55
examples/wxcomponents-template/manifest.json

@ -0,0 +1,55 @@
{
"name" : "wxcomponents-template",
"appid" : "__UNI__773C51E",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx":false,
"app-plus": { /* App */
"modules": { /* */
},
"distribute": { /* */
"android": { /* android */
"permissions": ["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios": { /* ios */
},
"sdkConfigs": { /* SDK */
}
}
},
"quickapp": { /* */
},
"mp-weixin": { /* */
"appid": "",
"setting" : {
"urlCheck" : true
}
}
}

37
examples/wxcomponents-template/pages.json

@ -0,0 +1,37 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "小程序组件示例"
}
},
{
"path": "pages/vant/vant",
"style": {
"navigationBarTitleText": "vant组件示例",
"usingComponents": {
"van-nav-bar": "/wxcomponents/vant-weapp/dist/nav-bar/index",
"van-icon": "/wxcomponents/vant-weapp/dist/icon/index"
}
}
},
{
"path": "pages/wux/wux",
"style": {
"navigationBarTitleText": "wux组件示例",
"usingComponents": {
"wux-calendar": "/wxcomponents/wux-weapp/dist/calendar/index",
"wux-cell-group": "/wxcomponents/wux-weapp/dist/cell-group/index",
"wux-cell": "/wxcomponents/wux-weapp/dist/cell/index"
}
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "小程序组件示例",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}

22
examples/wxcomponents-template/pages/index/index.vue

@ -0,0 +1,22 @@
<template>
<view class="content">
<navigator url="../vant/vant">
<button type="default">vant组件示例</button>
</navigator>
<navigator url="../wux/wux">
<button type="default">wux组件示例</button>
</navigator>
</view>
</template>
<script>
export default {
}
</script>
<style>
button {
margin-top: 20px;
}
</style>

32
examples/wxcomponents-template/pages/vant/vant.vue

@ -0,0 +1,32 @@
<template>
<view>
<view class="title">导航栏</view>
<van-nav-bar title="标题" left-text="返回" left-arrow @clickLeft="onClickLeft" @clickRight="onClickRight">
<van-icon name="search" slot="right" custom-class="icon" />
</van-nav-bar>
</view>
</template>
<script>
export default {
methods: {
onClickLeft() {
wx.showToast({
title: '点击返回',
icon: 'none'
});
},
onClickRight() {
wx.showToast({
title: '点击按钮',
icon: 'none'
});
}
}
}
</script>
<style>
</style>

80
examples/wxcomponents-template/pages/wux/wux.vue

@ -0,0 +1,80 @@
<template>
<view>
<view class="title">日历组件</view>
<wux-calendar id="wux-calendar" />
<wux-cell-group title="Calendar">
<wux-cell title="单选" :extra="value1" @click="openCalendar1"></wux-cell>
<wux-cell title="多选" :extra="value2" @click="openCalendar2"></wux-cell>
<wux-cell title="Direction = Vertical" :extra="value3" @click="openCalendar3"></wux-cell>
<wux-cell title="MinDate & MaxDate" :extra="value4" @click="openCalendar4"></wux-cell>
</wux-cell-group>
</view>
</template>
<script>
import {
$wuxCalendar
} from '@/wxcomponents/wux-weapp/dist/index.js'
export default {
data() {
return {
value1: [],
value2: [],
value3: [],
value4: [],
}
},
methods: {
openCalendar1() {
$wuxCalendar().open({
value: this.value1,
onChange: (values, displayValues) => {
console.log('onChange', values, displayValues)
this.value1 = displayValues
},
})
},
openCalendar2() {
$wuxCalendar().open({
value: this.value2,
multiple: true,
onChange: (values, displayValues) => {
console.log('onChange', values, displayValues)
this.value2 = displayValues
},
})
},
openCalendar3() {
$wuxCalendar().open({
value: this.value3,
direction: 'vertical',
onChange: (values, displayValues) => {
console.log('onChange', values, displayValues)
this.value3 = displayValues
},
})
},
openCalendar4() {
const now = new Date()
const minDate = now.getTime()
const maxDate = now.setDate(now.getDate() + 7)
$wuxCalendar().open({
value: this.value4,
minDate,
maxDate,
onChange: (values, displayValues) => {
console.log('onChange', values, displayValues)
this.value4 = displayValues
},
})
}
}
}
</script>
<style>
</style>

0
examples/wxcomponents-template/static/.gitkeep

29
examples/wxcomponents-template/wxcomponents/vant-weapp/dist/common/class-names.js

@ -0,0 +1,29 @@
const hasOwn = {}.hasOwnProperty;
export function classNames() {
const classes = [];
for (let i = 0; i < arguments.length; i++) {
const arg = arguments[i];
if (!arg) continue;
const argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg) && arg.length) {
const inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
} else if (argType === 'object') {
for (const key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(' ');
};

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save