Commit 0cef310fc0a9fc916c0fa288b827acd89098460b

Authored by 朱园亮
0 parents

erp项目移动端初始化

Too many changes to show.

To preserve performance only 44 of 2338 files are displayed.

  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="CompilerConfiguration">
  4 + <wildcardResourcePatterns>
  5 + <entry name="!?*.java" />
  6 + <entry name="!?*.form" />
  7 + <entry name="!?*.class" />
  8 + <entry name="!?*.groovy" />
  9 + <entry name="!?*.scala" />
  10 + <entry name="!?*.flex" />
  11 + <entry name="!?*.kt" />
  12 + <entry name="!?*.clj" />
  13 + </wildcardResourcePatterns>
  14 + </component>
  15 +</project>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module type="JAVA_MODULE" version="4">
  3 + <component name="NewModuleRootManager" inherit-compiler-output="true">
  4 + <exclude-output />
  5 + <content url="file://$MODULE_DIR$" />
  6 + <orderEntry type="inheritedJdk" />
  7 + <orderEntry type="sourceFolder" forTests="false" />
  8 + </component>
  9 +</module>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
  4 + <output url="file://$PROJECT_DIR$/out" />
  5 + </component>
  6 +</project>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ProjectModuleManager">
  4 + <modules>
  5 + <module fileurl="file://$PROJECT_DIR$/.idea/erp-mobile.iml" filepath="$PROJECT_DIR$/.idea/erp-mobile.iml" />
  6 + </modules>
  7 + </component>
  8 +</project>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="VcsDirectoryMappings">
  4 + <mapping directory="" vcs="Git" />
  5 + </component>
  6 +</project>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ChangeListManager">
  4 + <list default="true" id="22e3db16-f3f9-44cc-b7ca-0b5f75df2820" name="Changes" comment="" />
  5 + <option name="SHOW_DIALOG" value="false" />
  6 + <option name="HIGHLIGHT_CONFLICTS" value="true" />
  7 + <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
  8 + <option name="LAST_RESOLUTION" value="IGNORE" />
  9 + </component>
  10 + <component name="DebuggerManager">
  11 + <breakpoint_any converted="true">
  12 + <breakpoint>
  13 + <option name="NOTIFY_CAUGHT" value="true" />
  14 + <option name="NOTIFY_UNCAUGHT" value="true" />
  15 + <option name="ENABLED" value="false" />
  16 + <option name="LOG_ENABLED" value="false" />
  17 + <option name="LOG_EXPRESSION_ENABLED" value="false" />
  18 + <option name="REMOVE_AFTER_HIT" value="false" />
  19 + <option name="SUSPEND_POLICY" value="SuspendAll" />
  20 + <option name="SUSPEND" value="true" />
  21 + <option name="COUNT_FILTER_ENABLED" value="false" />
  22 + <option name="COUNT_FILTER" value="0" />
  23 + <option name="CONDITION_ENABLED" value="true" />
  24 + <option name="CLASS_FILTERS_ENABLED" value="false" />
  25 + <option name="INSTANCE_FILTERS_ENABLED" value="false" />
  26 + <option name="CONDITION" value="" />
  27 + <option name="LOG_MESSAGE" value="" />
  28 + </breakpoint>
  29 + <breakpoint>
  30 + <option name="NOTIFY_CAUGHT" value="true" />
  31 + <option name="NOTIFY_UNCAUGHT" value="true" />
  32 + <option name="ENABLED" value="false" />
  33 + <option name="LOG_ENABLED" value="false" />
  34 + <option name="LOG_EXPRESSION_ENABLED" value="false" />
  35 + <option name="REMOVE_AFTER_HIT" value="false" />
  36 + <option name="SUSPEND_POLICY" value="SuspendAll" />
  37 + <option name="SUSPEND" value="true" />
  38 + <option name="COUNT_FILTER_ENABLED" value="false" />
  39 + <option name="COUNT_FILTER" value="0" />
  40 + <option name="CONDITION_ENABLED" value="true" />
  41 + <option name="CLASS_FILTERS_ENABLED" value="false" />
  42 + <option name="INSTANCE_FILTERS_ENABLED" value="false" />
  43 + <option name="CONDITION" value="" />
  44 + <option name="LOG_MESSAGE" value="" />
  45 + </breakpoint>
  46 + </breakpoint_any>
  47 + <breakpoint_rules converted="true" />
  48 + <ui_properties converted="true" />
  49 + </component>
  50 + <component name="Git.Settings">
  51 + <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  52 + </component>
  53 + <component name="ProjectColorInfo">{
  54 + &quot;associatedIndex&quot;: 7
  55 +}</component>
  56 + <component name="ProjectId" id="34mEz1szZyt6R6ZltrQKMvCs3LN" />
  57 + <component name="ProjectViewState">
  58 + <option name="hideEmptyMiddlePackages" value="true" />
  59 + <option name="showLibraryContents" value="true" />
  60 + </component>
  61 + <component name="PropertiesComponent">{
  62 + &quot;keyToString&quot;: {
  63 + &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
  64 + &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
  65 + &quot;git-widget-placeholder&quot;: &quot;main&quot;,
  66 + &quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
  67 + &quot;last_opened_file_path&quot;: &quot;/Users/zhuyl/Documents/qgutech/erp-mobile&quot;,
  68 + &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
  69 + &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
  70 + }
  71 +}</component>
  72 + <component name="RunManager">
  73 + <configuration default="true" type="Applet" factoryName="Applet">
  74 + <option name="WIDTH" value="400" />
  75 + <option name="HEIGHT" value="300" />
  76 + <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
  77 + <module />
  78 + <method />
  79 + </configuration>
  80 + <configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
  81 + <Host>localhost</Host>
  82 + <Port>5050</Port>
  83 + </configuration>
  84 + <configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
  85 + <module name="" />
  86 + <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
  87 + <option name="PROGRAM_PARAMETERS" />
  88 + <method />
  89 + </configuration>
  90 + <configuration default="true" type="Application" factoryName="Application">
  91 + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
  92 + <method v="2">
  93 + <option name="Make" enabled="true" />
  94 + </method>
  95 + </configuration>
  96 + <configuration default="true" type="JUnit" factoryName="JUnit">
  97 + <option name="TEST_OBJECT" value="class" />
  98 + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
  99 + <option name="TEST_SEARCH_SCOPE">
  100 + <value defaultName="moduleWithDependencies" />
  101 + </option>
  102 + <method v="2">
  103 + <option name="Make" enabled="true" />
  104 + </method>
  105 + </configuration>
  106 + <configuration default="true" type="TestNG">
  107 + <option name="TEST_OBJECT" value="CLASS" />
  108 + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
  109 + <option name="TEST_SEARCH_SCOPE">
  110 + <value defaultName="moduleWithDependencies" />
  111 + </option>
  112 + <properties />
  113 + <listeners />
  114 + <method v="2">
  115 + <option name="Make" enabled="true" />
  116 + </method>
  117 + </configuration>
  118 + </component>
  119 + <component name="SharedIndexes">
  120 + <attachedChunks>
  121 + <set>
  122 + <option value="bundled-jdk-9823dce3aa75-a94e463ab2e7-intellij.indexing.shared.core-IU-243.26053.27" />
  123 + <option value="bundled-js-predefined-d6986cc7102b-1632447f56bf-JavaScript-IU-243.26053.27" />
  124 + </set>
  125 + </attachedChunks>
  126 + </component>
  127 + <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
  128 + <component name="SvnConfiguration" maxAnnotateRevisions="500" myUseAcceleration="nothing" myAutoUpdateAfterCommit="false" cleanupOnStartRun="false" SSL_PROTOCOLS="all">
  129 + <option name="USER" value="" />
  130 + <option name="PASSWORD" value="" />
  131 + <option name="mySSHConnectionTimeout" value="30000" />
  132 + <option name="mySSHReadTimeout" value="30000" />
  133 + <option name="LAST_MERGED_REVISION" />
  134 + <option name="MERGE_DRY_RUN" value="false" />
  135 + <option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
  136 + <option name="UPDATE_LOCK_ON_DEMAND" value="false" />
  137 + <option name="IGNORE_SPACES_IN_MERGE" value="false" />
  138 + <option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
  139 + <option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
  140 + <option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
  141 + <option name="FORCE_UPDATE" value="false" />
  142 + <option name="IGNORE_EXTERNALS" value="false" />
  143 + <myIsUseDefaultProxy>false</myIsUseDefaultProxy>
  144 + </component>
  145 + <component name="TaskManager">
  146 + <task active="true" id="Default" summary="Default task">
  147 + <changelist id="22e3db16-f3f9-44cc-b7ca-0b5f75df2820" name="Changes" comment="" />
  148 + <created>1761810605913</created>
  149 + <option name="number" value="Default" />
  150 + <option name="presentableId" value="Default" />
  151 + <updated>1761810605913</updated>
  152 + <workItem from="1761810607006" duration="20000" />
  153 + </task>
  154 + <servers />
  155 + </component>
  156 + <component name="TypeScriptGeneratedFilesManager">
  157 + <option name="version" value="3" />
  158 + </component>
  159 + <component name="VcsContentAnnotationSettings">
  160 + <option name="myLimit" value="2678400000" />
  161 + </component>
  162 +</project>
\ No newline at end of file
... ...
  1 +<script>
  2 + import config from './config'
  3 + import store from '@/store'
  4 + import { getToken } from '@/utils/auth'
  5 +
  6 + export default {
  7 + onLaunch: function() {
  8 + this.initApp()
  9 + },
  10 + methods: {
  11 + // 初始化应用
  12 + initApp() {
  13 + // 初始化应用配置
  14 + this.initConfig()
  15 + // 检查用户登录状态
  16 + //#ifdef H5
  17 + this.checkLogin()
  18 + //#endif
  19 + },
  20 + initConfig() {
  21 + this.globalData.config = config
  22 + },
  23 + checkLogin() {
  24 +
  25 + if (!getToken()) {
  26 + this.$tab.reLaunch('/pages/login')
  27 + }
  28 + }
  29 + }
  30 + }
  31 +</script>
  32 +
  33 +<style lang="scss">
  34 + @import '@/static/scss/index.scss'
  35 +</style>
... ...
  1 + Apache License
  2 + Version 2.0, January 2004
  3 + http://www.apache.org/licenses/
  4 +
  5 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 + 1. Definitions.
  8 +
  9 + "License" shall mean the terms and conditions for use, reproduction,
  10 + and distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 + "Licensor" shall mean the copyright owner or entity authorized by
  13 + the copyright owner that is granting the License.
  14 +
  15 + "Legal Entity" shall mean the union of the acting entity and all
  16 + other entities that control, are controlled by, or are under common
  17 + control with that entity. For the purposes of this definition,
  18 + "control" means (i) the power, direct or indirect, to cause the
  19 + direction or management of such entity, whether by contract or
  20 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
  21 + outstanding shares, or (iii) beneficial ownership of such entity.
  22 +
  23 + "You" (or "Your") shall mean an individual or Legal Entity
  24 + exercising permissions granted by this License.
  25 +
  26 + "Source" form shall mean the preferred form for making modifications,
  27 + including but not limited to software source code, documentation
  28 + source, and configuration files.
  29 +
  30 + "Object" form shall mean any form resulting from mechanical
  31 + transformation or translation of a Source form, including but
  32 + not limited to compiled object code, generated documentation,
  33 + and conversions to other media types.
  34 +
  35 + "Work" shall mean the work of authorship, whether in Source or
  36 + Object form, made available under the License, as indicated by a
  37 + copyright notice that is included in or attached to the work
  38 + (an example is provided in the Appendix below).
  39 +
  40 + "Derivative Works" shall mean any work, whether in Source or Object
  41 + form, that is based on (or derived from) the Work and for which the
  42 + editorial revisions, annotations, elaborations, or other modifications
  43 + represent, as a whole, an original work of authorship. For the purposes
  44 + of this License, Derivative Works shall not include works that remain
  45 + separable from, or merely link (or bind by name) to the interfaces of,
  46 + the Work and Derivative Works thereof.
  47 +
  48 + "Contribution" shall mean any work of authorship, including
  49 + the original version of the Work and any modifications or additions
  50 + to that Work or Derivative Works thereof, that is intentionally
  51 + submitted to Licensor for inclusion in the Work by the copyright owner
  52 + or by an individual or Legal Entity authorized to submit on behalf of
  53 + the copyright owner. For the purposes of this definition, "submitted"
  54 + means any form of electronic, verbal, or written communication sent
  55 + to the Licensor or its representatives, including but not limited to
  56 + communication on electronic mailing lists, source code control systems,
  57 + and issue tracking systems that are managed by, or on behalf of, the
  58 + Licensor for the purpose of discussing and improving the Work, but
  59 + excluding communication that is conspicuously marked or otherwise
  60 + designated in writing by the copyright owner as "Not a Contribution."
  61 +
  62 + "Contributor" shall mean Licensor and any individual or Legal Entity
  63 + on behalf of whom a Contribution has been received by Licensor and
  64 + subsequently incorporated within the Work.
  65 +
  66 + 2. Grant of Copyright License. Subject to the terms and conditions of
  67 + this License, each Contributor hereby grants to You a perpetual,
  68 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  69 + copyright license to reproduce, prepare Derivative Works of,
  70 + publicly display, publicly perform, sublicense, and distribute the
  71 + Work and such Derivative Works in Source or Object form.
  72 +
  73 + 3. Grant of Patent License. Subject to the terms and conditions of
  74 + this License, each Contributor hereby grants to You a perpetual,
  75 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  76 + (except as stated in this section) patent license to make, have made,
  77 + use, offer to sell, sell, import, and otherwise transfer the Work,
  78 + where such license applies only to those patent claims licensable
  79 + by such Contributor that are necessarily infringed by their
  80 + Contribution(s) alone or by combination of their Contribution(s)
  81 + with the Work to which such Contribution(s) was submitted. If You
  82 + institute patent litigation against any entity (including a
  83 + cross-claim or counterclaim in a lawsuit) alleging that the Work
  84 + or a Contribution incorporated within the Work constitutes direct
  85 + or contributory patent infringement, then any patent licenses
  86 + granted to You under this License for that Work shall terminate
  87 + as of the date such litigation is filed.
  88 +
  89 + 4. Redistribution. You may reproduce and distribute copies of the
  90 + Work or Derivative Works thereof in any medium, with or without
  91 + modifications, and in Source or Object form, provided that You
  92 + meet the following conditions:
  93 +
  94 + (a) You must give any other recipients of the Work or
  95 + Derivative Works a copy of this License; and
  96 +
  97 + (b) You must cause any modified files to carry prominent notices
  98 + stating that You changed the files; and
  99 +
  100 + (c) You must retain, in the Source form of any Derivative Works
  101 + that You distribute, all copyright, patent, trademark, and
  102 + attribution notices from the Source form of the Work,
  103 + excluding those notices that do not pertain to any part of
  104 + the Derivative Works; and
  105 +
  106 + (d) If the Work includes a "NOTICE" text file as part of its
  107 + distribution, then any Derivative Works that You distribute must
  108 + include a readable copy of the attribution notices contained
  109 + within such NOTICE file, excluding those notices that do not
  110 + pertain to any part of the Derivative Works, in at least one
  111 + of the following places: within a NOTICE text file distributed
  112 + as part of the Derivative Works; within the Source form or
  113 + documentation, if provided along with the Derivative Works; or,
  114 + within a display generated by the Derivative Works, if and
  115 + wherever such third-party notices normally appear. The contents
  116 + of the NOTICE file are for informational purposes only and
  117 + do not modify the License. You may add Your own attribution
  118 + notices within Derivative Works that You distribute, alongside
  119 + or as an addendum to the NOTICE text from the Work, provided
  120 + that such additional attribution notices cannot be construed
  121 + as modifying the License.
  122 +
  123 + You may add Your own copyright statement to Your modifications and
  124 + may provide additional or different license terms and conditions
  125 + for use, reproduction, or distribution of Your modifications, or
  126 + for any such Derivative Works as a whole, provided Your use,
  127 + reproduction, and distribution of the Work otherwise complies with
  128 + the conditions stated in this License.
  129 +
  130 + 5. Submission of Contributions. Unless You explicitly state otherwise,
  131 + any Contribution intentionally submitted for inclusion in the Work
  132 + by You to the Licensor shall be under the terms and conditions of
  133 + this License, without any additional terms or conditions.
  134 + Notwithstanding the above, nothing herein shall supersede or modify
  135 + the terms of any separate license agreement you may have executed
  136 + with Licensor regarding such Contributions.
  137 +
  138 + 6. Trademarks. This License does not grant permission to use the trade
  139 + names, trademarks, service marks, or product names of the Licensor,
  140 + except as required for reasonable and customary use in describing the
  141 + origin of the Work and reproducing the content of the NOTICE file.
  142 +
  143 + 7. Disclaimer of Warranty. Unless required by applicable law or
  144 + agreed to in writing, Licensor provides the Work (and each
  145 + Contributor provides its Contributions) on an "AS IS" BASIS,
  146 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  147 + implied, including, without limitation, any warranties or conditions
  148 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  149 + PARTICULAR PURPOSE. You are solely responsible for determining the
  150 + appropriateness of using or redistributing the Work and assume any
  151 + risks associated with Your exercise of permissions under this License.
  152 +
  153 + 8. Limitation of Liability. In no event and under no legal theory,
  154 + whether in tort (including negligence), contract, or otherwise,
  155 + unless required by applicable law (such as deliberate and grossly
  156 + negligent acts) or agreed to in writing, shall any Contributor be
  157 + liable to You for damages, including any direct, indirect, special,
  158 + incidental, or consequential damages of any character arising as a
  159 + result of this License or out of the use or inability to use the
  160 + Work (including but not limited to damages for loss of goodwill,
  161 + work stoppage, computer failure or malfunction, or any and all
  162 + other commercial damages or losses), even if such Contributor
  163 + has been advised of the possibility of such damages.
  164 +
  165 + 9. Accepting Warranty or Additional Liability. While redistributing
  166 + the Work or Derivative Works thereof, You may choose to offer,
  167 + and charge a fee for, acceptance of support, warranty, indemnity,
  168 + or other liability obligations and/or rights consistent with this
  169 + License. However, in accepting such obligations, You may act only
  170 + on Your own behalf and on Your sole responsibility, not on behalf
  171 + of any other Contributor, and only if You agree to indemnify,
  172 + defend, and hold each Contributor harmless for any liability
  173 + incurred by, or claims asserted against, such Contributor by reason
  174 + of your accepting any such warranty or additional liability.
  175 +
  176 + END OF TERMS AND CONDITIONS
  177 +
  178 + APPENDIX: How to apply the Apache License to your work.
  179 +
  180 + To apply the Apache License to your work, attach the following
  181 + boilerplate notice, with the fields enclosed by brackets "[]"
  182 + replaced with your own identifying information. (Don't include
  183 + the brackets!) The text should be enclosed in the appropriate
  184 + comment syntax for the file format. We also recommend that a
  185 + file or class name and description of purpose be included on the
  186 + same "printed page" as the copyright notice for easier
  187 + identification within third-party archives.
  188 +
  189 + Copyright [yyyy] [name of copyright owner]
  190 +
  191 + Licensed under the Apache License, Version 2.0 (the "License");
  192 + you may not use this file except in compliance with the License.
  193 + You may obtain a copy of the License at
  194 +
  195 + http://www.apache.org/licenses/LICENSE-2.0
  196 +
  197 + Unless required by applicable law or agreed to in writing, software
  198 + distributed under the License is distributed on an "AS IS" BASIS,
  199 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  200 + See the License for the specific language governing permissions and
  201 + limitations under the License.
... ...
  1 +# 配套 星云erp-手机版
  2 +
  3 +#### Description
  4 +一套比较火的erp移动版配套,选了 星云erp v3版。功能和星云erp pc版1比1。完全没有商用限制。技术探讨请加QQ:3783722918。为了更好完善更多功能也欢迎加入我们团队成为共同开发者。
  5 +
  6 +#### Software Architecture
  7 +Software architecture description
  8 +
  9 +#### Installation
  10 +
  11 +1. xxxx
  12 +2. xxxx
  13 +3. xxxx
  14 +
  15 +#### Instructions
  16 +
  17 +1. xxxx
  18 +2. xxxx
  19 +3. xxxx
  20 +
  21 +#### Contribution
  22 +
  23 +1. Fork the repository
  24 +2. Create Feat_xxx branch
  25 +3. Commit your code
  26 +4. Create Pull Request
  27 +
  28 +
  29 +#### Gitee Feature
  30 +
  31 +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
  32 +2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
  33 +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
  34 +4. The most valuable open source project [GVP](https://gitee.com/gvp)
  35 +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
  36 +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
... ...
  1 +#
  2 +<h1 align="center">erp-移动版(支持saas、支持网络打印)</h1>
  3 +<p align="center">
  4 + <a href="http://wecando21cn.com">
  5 + <img src="https://img.shields.io/badge/License-apache2.0-green.svg?style=flat" />
  6 + </a>
  7 + <a href="#">
  8 + <img src="https://img.shields.io/badge/Edition-1.1-blue.svg" />
  9 + </a>
  10 + <a href="#">
  11 + <img src="https://img.shields.io/badge/download-80m-red.svg" />
  12 + </a>
  13 +</p>
  14 +<p align="center">
  15 + <b>如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢!</b>
  16 +</p>
  17 +<div align="center">
  18 +
  19 +[在线演示](http://fetoo.wecando21cn.com/) |
  20 +[技术文档](https://docs.qq.com/doc/p/6ef0737d449941b8adf4f4b5853a2f03d3d02ad7) |
  21 +[源码结构](https://docs.qq.com/doc/p/303e09fba738dca76f0aea17d8de67757290bfdd)
  22 +</div>
  23 +
  24 +### 介绍
  25 +
  26 +基于uniapp开发的移动版erp,适配h5、小程序和app。解决中小企业客户跟进不及时、财务数据混乱、订单跟踪难等难题。实时实地库存盘点、采购入库核算、出库核算等pda实地操作。支持saas、支持单据扫码、支持单据打印。
  27 +(该移动端也兼容若依框架)
  28 +
  29 +### 功能说明(专业版)
  30 +
  31 +
  32 +| 系统功能 | 功能描述(支持扫码查询等) |
  33 +|------|-----------------------------|
  34 +| 基础信息 | 客户管理、供应商管理、会员基础信息、仓库管理、门店管理、支付管理、地址管理、物流管理 |
  35 +| 商品中心 | 商品主数据、商品分类、品牌、属性(自定义属性) |
  36 +| 采购管理 | 采购订单、采购收货单、采购退货单 |
  37 +| 销售管理 | 销售订单、出库单、退货单 |
  38 +| 零售管理 | 零售出库单、退货单 |
  39 +| 库存管理 | 商品库存、变动记录、数量调整、成本调整、调整原因、仓库调拨 |
  40 +| 库存盘点 | 盘点参数设置、预先盘点单管理、盘点任务管理、盘点单管理 |
  41 +| 结算管理 | 供应商/客户费用单、预付款单、对账单、结算单、收入/支出项目 |
  42 +| 其他功能 | 消息通知、订单图表、本地单据打印 |
  43 +
  44 +打印插件:[http://xy.wecando21cn.com/打印插件.zip](http://xy.wecando21cn.com/打印插件.zip)
  45 +
  46 +### 在线演示
  47 +#### 移动端:
  48 +在线演示:[http://fetoo.wecando21cn.com/](http://fetoo.wecando21cn.com/)
  49 +
  50 +用户名: "1000@admin", 密码: "admin"
  51 +
  52 +#### PC端(集成多报表和打印模板,支持批量打印单据)
  53 +在线演示:[http://cderp.pc.wecando21cn.com/](http://cderp.pc.wecando21cn.com/)
  54 +
  55 +用户名: "admin", 密码: "admin"
  56 +
  57 +源码地址:[https://gitee.com/i-love-ai/erp-vue---supports-saas](https://gitee.com/i-love-ai/erp-vue---supports-saas)
  58 +
  59 +#### 服务端
  60 +源码地址:[https://gitee.com/i-love-ai/erp-server---supports-saas](https://gitee.com/i-love-ai/erp-server---supports-saas)
  61 +
  62 +
  63 +
  64 +<h3>专业版源代码,可咨询微信: <b>yuwosuoyuan106</b> </h3>
  65 +
  66 +| 更多演示 | 技术交流群①463950209 |
  67 +| ------------ | ------------ |
  68 +|![输入图片说明](static/images/wx.jpg)|![输入图片说明](ui/qq.png)|
  69 +
  70 +
  71 +### 界面展示
  72 +<table>
  73 + <tr>
  74 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/1.png"/></td>
  75 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/2.png"/></td>
  76 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/3.png"/></td>
  77 + </tr>
  78 + <tr>
  79 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/4.png"/></td>
  80 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/5png.png"/></td>
  81 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/6.png"/></td>
  82 + </tr>
  83 + <tr>
  84 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/7.png"/></td>
  85 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/8.png"/></td>
  86 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/9.png"/></td>
  87 + </tr>
  88 + </tr>
  89 + <tr>
  90 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/10.png"/></td>
  91 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/11png.png"/></td>
  92 + <td><img src="https://gitee.com/i-love-ai/xy-mobile-master/raw/master/ui/12.png"/></td>
  93 + </tr>
  94 +</table>
  95 +
  96 +### 安装教程
  97 +
  98 +#### 后端:
  99 +参考[ERP服务端](https://gitee.com/i-love-ai/erp-server---supports-saas)的相关配置,这里不赘述。
  100 +
  101 +
  102 +#### 前端:
  103 +
  104 +* 应用框架基于[uniapp](https://uniapp.dcloud.net.cn/),支持小程序、H5、Android和IOS。
  105 +* 前端组件采用[uni-ui](https://github.com/dcloudio/uni-ui),全端兼容的高性能UI框架。
  106 +
  107 +* 使用Hbuilder 打开项目
  108 +* 在config.js中,配置baseUrl,这个为后端接口地址
  109 + baseUrl: 'http://localhost:8085',
  110 +* 运行项目,到浏览器或者小程序即可运行
  111 +### 特别鸣谢
  112 +
  113 +排名不分先后,感谢这些软件的开发者:星云erp、vue、echarts、tree-table-vue、swiper、form-create等,如有遗漏请联系我!
  114 +
  115 +### 免责声明
  116 +
  117 +因为接口端直接使用 星云erp,接口端请自行遵守原作的协议。移动版不受限。
\ No newline at end of file
... ...
  1 +import request from '@/utils/request'
  2 +// import contentTypeEnum from '@/enums/httpEnums'
  3 +
  4 +const baseUrl = '/sale/config';
  5 +const region = 'cloud-api';
  6 +
  7 +/**
  8 + * 查询详情
  9 + */
  10 +export function getConfig(){
  11 + return request({
  12 + url: baseUrl,
  13 + method: 'get',
  14 +
  15 + })
  16 +}
  17 +
  18 +
  19 +/**
  20 + * 修改
  21 + */
  22 +export function updateConfig(data) {
  23 + return request(
  24 + {
  25 + url: baseUrl,
  26 + data: data,
  27 + method: 'put',
  28 + contentType: 'application/x-www-form-urlencoded;charset=UTF-8',
  29 +
  30 + }
  31 + );
  32 +}
... ...
  1 +import request from '@/utils/request'
  2 +// import contentTypeEnum from '@/enums/httpEnums'
  3 +
  4 +
  5 +const baseUrl = '/stock/take/config';
  6 +const region = 'cloud-api';
  7 +
  8 +/**
  9 + * 查询详情
  10 + */
  11 +export function getConfig(){
  12 + return request({
  13 + url: baseUrl,
  14 + method: 'get',
  15 +
  16 + })
  17 +}
  18 +
  19 +
  20 +/**
  21 + * 修改
  22 + */
  23 +export function updateConfig(data) {
  24 + return request(
  25 + {
  26 + url: baseUrl,
  27 + data: data,
  28 + method: 'put',
  29 + contentType: 'application/x-www-form-urlencoded;charset=UTF-8',
  30 +
  31 + }
  32 + );
  33 +}
... ...
  1 +import upload from '@/utils/upload'
  2 +import request from '@/utils/request'
  3 +const baseUrl = '/chart';
  4 + const region = 'cloud-api';
  5 +export function orderChart(){
  6 + return request({
  7 + url: baseUrl + '/order',
  8 + method: 'get',
  9 +
  10 + })
  11 +}
\ No newline at end of file
... ...
  1 +import request from '@/utils/request'
  2 +
  3 +// 登录方法
  4 +export function login(username, password, captcha, sn) {
  5 +
  6 + const data = {
  7 + username,
  8 + password,
  9 + captcha,
  10 + sn
  11 + }
  12 +
  13 + return request({
  14 + 'url': '/auth/login',
  15 + headers: {
  16 + isToken: false
  17 + },
  18 + 'method': 'post',
  19 + 'data': data,
  20 + 'params':data,
  21 + })
  22 +}
  23 +
  24 +// 注册方法
  25 +export function register(data) {
  26 + return request({
  27 + url: '/register',
  28 + headers: {
  29 + isToken: false
  30 + },
  31 + method: 'post',
  32 + data: data
  33 + })
  34 +}
  35 +
  36 +// 获取用户详细信息
  37 +export function getInfo() {
  38 + return request({
  39 + 'url': '/getInfo',
  40 + 'method': 'get'
  41 + })
  42 +}
  43 +
  44 +// 退出方法
  45 +export function logout() {
  46 + return request({
  47 + 'url': '/auth/logout',
  48 + 'method': 'post'
  49 + })
  50 +}
  51 +
  52 +// 获取验证码
  53 +export function getCodeImg() {
  54 + return request({
  55 + 'url': '/auth/captcha',
  56 + headers: {
  57 + isToken: false
  58 + },
  59 + method: 'get',
  60 + timeout: 20000
  61 + })
  62 +}
... ...
  1 +export interface A4ExcelPortraitPrintBo {
  2 + /**
  3 + * 打印方向及纸张类型 1---纵向打印,固定纸张; 2---横向打印,固定纸张; 3---纵向打印,宽度固定,高度按打印内容的高度自适应;0---方向不定,由操作者自行选择或按打印机缺省设置。
  4 + */
  5 + orient: number;
  6 +
  7 + /**
  8 + * 纸张宽,单位为0.1mm 譬如该参数值为45,则表示4.5mm,计量精度是0.1mm。
  9 + */
  10 + pageWidth: number;
  11 +
  12 + /**
  13 + * 固定纸张时该参数是纸张高;高度自适应时该参数是纸张底边的空白高,计量单位与纸张宽一样。
  14 + */
  15 + pageHeight: number;
  16 +
  17 + /**
  18 + * 纸张类型名, pageWidth等于零时本参数才有效,具体名称参见操作系统打印服务属性中的格式定义。 关键字“CreateCustomPage”会在系统内建立一个名称为“LodopCustomPage”自定义纸张类型。
  19 + */
  20 + pageName: string;
  21 +
  22 + /**
  23 + * 上边距 单位:mm
  24 + */
  25 + marginTop: number;
  26 +
  27 + /**
  28 + * 左边距 单位:mm
  29 + */
  30 + marginLeft: number;
  31 +
  32 + /**
  33 + * 右边距 单位:mm
  34 + */
  35 + marginRight: number;
  36 +
  37 + /**
  38 + * 下边距 单位:mm
  39 + */
  40 + marginBottom: number;
  41 +
  42 + /**
  43 + * 打印html内容
  44 + */
  45 + html: string;
  46 +}
... ...
  1 +export interface PageResult<T> {
  2 + /**
  3 + * 是否有上一页
  4 + */
  5 + hasPrev: boolean;
  6 +
  7 + /**
  8 + * 是否有下一页
  9 + */
  10 + hasNext: boolean;
  11 +
  12 + /**
  13 + * 总记录数
  14 + */
  15 + totalCount: number;
  16 +
  17 + /**
  18 + * 每页数据量
  19 + */
  20 + pageSize: number;
  21 +
  22 + /**
  23 + * 当前页码
  24 + */
  25 + pageIndex: number;
  26 +
  27 + /**
  28 + * 总页数
  29 + */
  30 + totalPage: number;
  31 +
  32 + /**
  33 + * 数据
  34 + */
  35 + datas: T[] | null;
  36 +
  37 + /**
  38 + * 附加数据
  39 + */
  40 + extra: Map<any, any>;
  41 +}
... ...
  1 +export interface PageVo {
  2 + /**
  3 + * 当前页码
  4 + */
  5 + pageIndex: number;
  6 + /**
  7 + * 每页条数
  8 + */
  9 + pageSize: number;
  10 +}
... ...
  1 +import { PageVo } from '@/api/model/pageVo';
  2 +
  3 +export interface SortPageVo extends PageVo {
  4 + /**
  5 + * 排序字段
  6 + */
  7 + sortField: string;
  8 + /**
  9 + * 排序类型
  10 + */
  11 + sortOrder: string;
  12 +}
... ...
  1 +import upload from '@/utils/upload'
  2 +import request from '@/utils/request'
  3 + const baseUrl = '/center';
  4 + const region = 'cloud-api';
  5 +
  6 +
  7 + const selectorBaseUrl = '/selector';
  8 +/**
  9 + * 查询selector
  10 + */
  11 +export function userSelector(data){
  12 +
  13 + return request({
  14 + url: selectorBaseUrl + '/user',
  15 + method: 'get',
  16 + params: data
  17 + });
  18 +}
  19 +
  20 +// 用户密码重置
  21 +export function updateUserPwd(oldPsw,newPsw,confirmPsw){
  22 +
  23 + const data = {
  24 + oldPsw,
  25 + newPsw,
  26 + confirmPsw
  27 + }
  28 + return request({
  29 + url: baseUrl + '/password',
  30 + method: 'put',
  31 + params: data
  32 + })
  33 +}
  34 +
  35 +// 查询用户个人信息
  36 +export function getUserProfile() {
  37 + return request({
  38 +
  39 + url: baseUrl + '/info',
  40 + method: 'get'
  41 + })
  42 +}
  43 +
  44 +// 修改用户个人信息
  45 +export function updateUserProfile(data) {
  46 + return request({
  47 + url: '/system/user/profile',
  48 + method: 'put',
  49 + data: data
  50 + })
  51 +}
  52 +
  53 +// 用户头像上传
  54 +export function uploadAvatar(data) {
  55 + return upload({
  56 + url: '/system/user/profile/avatar',
  57 + name: data.name,
  58 + filePath: data.filePath
  59 + })
  60 +}
... ...
  1 +<template>
  2 + <div :class="className" :style="{ height: height, width: width }"></div>
  3 +</template>
  4 +
  5 +<script>
  6 + import * as echarts from 'echarts';
  7 + //import resize from './mixins/resize';
  8 +
  9 + export default defineComponent({
  10 + // mixins: [resize],
  11 + props: {
  12 + className: {
  13 + type: String,
  14 + default: 'chart',
  15 + },
  16 + width: {
  17 + type: String,
  18 + default: '100%',
  19 + },
  20 + height: {
  21 + type: String,
  22 + default: '350px',
  23 + },
  24 + autoResize: {
  25 + type: Boolean,
  26 + default: true,
  27 + },
  28 + chartData: {
  29 + type: Object,
  30 + required: true,
  31 + },
  32 + },
  33 + data() {
  34 + return {
  35 + chart: null,
  36 + };
  37 + },
  38 + watch: {
  39 + chartData: {
  40 + deep: true,
  41 + handler(val) {
  42 + this.setOptions(val);
  43 + },
  44 + },
  45 + },
  46 + mounted() {
  47 + this.$nextTick(() => {
  48 + this.initChart();
  49 + });
  50 + },
  51 + beforeUnmount() {
  52 + if (!this.chart) {
  53 + return;
  54 + }
  55 + this.chart.dispose();
  56 + this.chart = null;
  57 + },
  58 + methods: {
  59 + initChart() {
  60 + this.$nextTick(() => {
  61 + this.chart = echarts.init(this.$el, 'macarons');
  62 + this.setOptions(this.chartData);
  63 + });
  64 + },
  65 + setOptions({ title, xAxisDatas, totalAmountDatas, totalNumDatas } = {}) {
  66 + if (this.chart) {
  67 + this.chart.setOption({
  68 + title: {
  69 + left: 'center',
  70 + text: title || '',
  71 + },
  72 + xAxis: {
  73 + data: [...(xAxisDatas || [])],
  74 + boundaryGap: false,
  75 + axisTick: {
  76 + show: false,
  77 + },
  78 + },
  79 + grid: {
  80 + left: 10,
  81 + right: 10,
  82 + bottom: 20,
  83 + top: 30,
  84 + containLabel: true,
  85 + },
  86 + tooltip: {
  87 + trigger: 'axis',
  88 + axisPointer: {
  89 + type: 'cross',
  90 + },
  91 + padding: [5, 10],
  92 + },
  93 + yAxis: {
  94 + axisTick: {
  95 + show: false,
  96 + },
  97 + },
  98 + legend: {
  99 + left: 'right',
  100 + data: ['单据总金额', '单据总数量'],
  101 + },
  102 + series: [
  103 + {
  104 + name: '单据总金额',
  105 + itemStyle: {
  106 + normal: {
  107 + color: '#FF005A',
  108 + lineStyle: {
  109 + color: '#FF005A',
  110 + width: 2,
  111 + },
  112 + },
  113 + },
  114 + smooth: true,
  115 + type: 'line',
  116 + data: totalAmountDatas,
  117 + animationDuration: 2800,
  118 + animationEasing: 'cubicInOut',
  119 + },
  120 + {
  121 + name: '单据总数量',
  122 + smooth: true,
  123 + type: 'line',
  124 + itemStyle: {
  125 + normal: {
  126 + color: '#3888fa',
  127 + lineStyle: {
  128 + color: '#3888fa',
  129 + width: 2,
  130 + },
  131 + areaStyle: {
  132 + color: '#f3f8ff',
  133 + },
  134 + },
  135 + },
  136 + data: totalNumDatas,
  137 + animationDuration: 2800,
  138 + animationEasing: 'quadraticOut',
  139 + },
  140 + ],
  141 + });
  142 + }
  143 + },
  144 + },
  145 + });
  146 +</script>
... ...
  1 +import { debounce } from '@/utils'
  2 +
  3 +export default {
  4 + data() {
  5 + return {
  6 + $_sidebarElm: null,
  7 + $_resizeHandler: null
  8 + }
  9 + },
  10 + mounted() {
  11 + this.$_resizeHandler = debounce(() => {
  12 + if (this.chart) {
  13 + this.chart.resize()
  14 + }
  15 + }, 100)
  16 + this.$_initResizeEvent()
  17 + this.$_initSidebarResizeEvent()
  18 + },
  19 + beforeDestroy() {
  20 + this.$_destroyResizeEvent()
  21 + this.$_destroySidebarResizeEvent()
  22 + },
  23 + // to fixed bug when cached by keep-alive
  24 + // https://github.com/PanJiaChen/vue-element-admin/issues/2116
  25 + activated() {
  26 + this.$_initResizeEvent()
  27 + this.$_initSidebarResizeEvent()
  28 + },
  29 + deactivated() {
  30 + this.$_destroyResizeEvent()
  31 + this.$_destroySidebarResizeEvent()
  32 + },
  33 + methods: {
  34 + // use $_ for mixins properties
  35 + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
  36 + $_initResizeEvent() {
  37 + window.addEventListener('resize', this.$_resizeHandler)
  38 + },
  39 + $_destroyResizeEvent() {
  40 + window.removeEventListener('resize', this.$_resizeHandler)
  41 + },
  42 + $_sidebarResizeHandler(e) {
  43 + if (e.propertyName === 'width') {
  44 + this.$_resizeHandler()
  45 + }
  46 + },
  47 + $_initSidebarResizeEvent() {
  48 + this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
  49 + this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
  50 + },
  51 + $_destroySidebarResizeEvent() {
  52 + this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
  53 + }
  54 + }
  55 +}
... ...
  1 +const cacheChart = {}
  2 +const fontSizeReg = /([\d\.]+)px/;
  3 +class EventEmit {
  4 + constructor() {
  5 + this.__events = {};
  6 + }
  7 + on(type, listener) {
  8 + if (!type || !listener) {
  9 + return;
  10 + }
  11 + const events = this.__events[type] || [];
  12 + events.push(listener);
  13 + this.__events[type] = events;
  14 + }
  15 + emit(type, e) {
  16 + if (type.constructor === Object) {
  17 + e = type;
  18 + type = e && e.type;
  19 + }
  20 + if (!type) {
  21 + return;
  22 + }
  23 + const events = this.__events[type];
  24 + if (!events || !events.length) {
  25 + return;
  26 + }
  27 + events.forEach((listener) => {
  28 + listener.call(this, e);
  29 + });
  30 + }
  31 + off(type, listener) {
  32 + const __events = this.__events;
  33 + const events = __events[type];
  34 + if (!events || !events.length) {
  35 + return;
  36 + }
  37 + if (!listener) {
  38 + delete __events[type];
  39 + return;
  40 + }
  41 + for (let i = 0, len = events.length; i < len; i++) {
  42 + if (events[i] === listener) {
  43 + events.splice(i, 1);
  44 + i--;
  45 + }
  46 + }
  47 + }
  48 +}
  49 +class Image {
  50 + constructor() {
  51 + this.currentSrc = null
  52 + this.naturalHeight = 0
  53 + this.naturalWidth = 0
  54 + this.width = 0
  55 + this.height = 0
  56 + this.tagName = 'IMG'
  57 + }
  58 + set src(src) {
  59 + this.currentSrc = src
  60 + uni.getImageInfo({
  61 + src,
  62 + success: (res) => {
  63 + this.naturalWidth = this.width = res.width
  64 + this.naturalHeight = this.height = res.height
  65 + this.onload()
  66 + },
  67 + fail: () => {
  68 + this.onerror()
  69 + }
  70 + })
  71 + }
  72 + get src() {
  73 + return this.currentSrc
  74 + }
  75 +}
  76 +class OffscreenCanvas {
  77 + constructor(ctx, com, canvasId) {
  78 + this.tagName = 'canvas'
  79 + this.com = com
  80 + this.canvasId = canvasId
  81 + this.ctx = ctx
  82 + }
  83 + set width(w) {
  84 + this.com.offscreenWidth = w
  85 + }
  86 + set height(h) {
  87 + this.com.offscreenHeight = h
  88 + }
  89 + get width() {
  90 + return this.com.offscreenWidth || 0
  91 + }
  92 + get height() {
  93 + return this.com.offscreenHeight || 0
  94 + }
  95 + getContext(type) {
  96 + return this.ctx
  97 + }
  98 + getImageData() {
  99 + return new Promise((resolve, reject) => {
  100 + this.com.$nextTick(() => {
  101 + uni.canvasGetImageData({
  102 + x:0,
  103 + y:0,
  104 + width: this.com.offscreenWidth,
  105 + height: this.com.offscreenHeight,
  106 + canvasId: this.canvasId,
  107 + success: (res) => {
  108 + resolve(res)
  109 + },
  110 + fail: (err) => {
  111 + reject(err)
  112 + },
  113 + }, this.com)
  114 + })
  115 + })
  116 + }
  117 +}
  118 +export class Canvas {
  119 + constructor(ctx, com, isNew, canvasNode={}) {
  120 + cacheChart[com.canvasId] = {ctx}
  121 + this.canvasId = com.canvasId;
  122 + this.chart = null;
  123 + this.isNew = isNew
  124 + this.tagName = 'canvas'
  125 + this.canvasNode = canvasNode;
  126 + this.com = com;
  127 + if (!isNew) {
  128 + this._initStyle(ctx)
  129 + }
  130 + this._initEvent();
  131 + this._ee = new EventEmit()
  132 + }
  133 + getContext(type) {
  134 + if (type === '2d') {
  135 + return this.ctx;
  136 + }
  137 + }
  138 + setAttribute(key, value) {
  139 + if(key === 'aria-label') {
  140 + this.com['ariaLabel'] = value
  141 + }
  142 + }
  143 + setChart(chart) {
  144 + this.chart = chart;
  145 + }
  146 + createOffscreenCanvas(param){
  147 + if(!this.children) {
  148 + this.com.isOffscreenCanvas = true
  149 + this.com.offscreenWidth = param.width||300
  150 + this.com.offscreenHeight = param.height||300
  151 + const com = this.com
  152 + const canvasId = this.com.offscreenCanvasId
  153 + const context = uni.createCanvasContext(canvasId, this.com)
  154 + this._initStyle(context)
  155 + this.children = new OffscreenCanvas(context, com, canvasId)
  156 + }
  157 + return this.children
  158 + }
  159 + appendChild(child) {
  160 + console.log('child', child)
  161 + }
  162 + dispatchEvent(type, e) {
  163 + if(typeof type == 'object') {
  164 + this._ee.emit(type.type, type);
  165 + } else {
  166 + this._ee.emit(type, e);
  167 + }
  168 + return true
  169 + }
  170 + attachEvent() {
  171 + }
  172 + detachEvent() {
  173 + }
  174 + addEventListener(type, listener) {
  175 + this._ee.on(type, listener)
  176 + }
  177 + removeEventListener(type, listener) {
  178 + this._ee.off(type, listener)
  179 + }
  180 + _initCanvas(zrender, ctx) {
  181 + // zrender.util.getContext = function() {
  182 + // return ctx;
  183 + // };
  184 + // zrender.util.$override('measureText', function(text, font) {
  185 + // ctx.font = font || '12px sans-serif';
  186 + // return ctx.measureText(text, font);
  187 + // });
  188 + }
  189 + _initStyle(ctx, child) {
  190 + const styles = [
  191 + 'fillStyle',
  192 + 'strokeStyle',
  193 + 'fontSize',
  194 + 'globalAlpha',
  195 + 'opacity',
  196 + 'textAlign',
  197 + 'textBaseline',
  198 + 'shadow',
  199 + 'lineWidth',
  200 + 'lineCap',
  201 + 'lineJoin',
  202 + 'lineDash',
  203 + 'miterLimit',
  204 + // #ifdef H5
  205 + 'font',
  206 + // #endif
  207 + ];
  208 + const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g;
  209 + styles.forEach(style => {
  210 + Object.defineProperty(ctx, style, {
  211 + set: value => {
  212 + // #ifdef H5
  213 + if (style === 'font' && fontSizeReg.test(value)) {
  214 + const match = fontSizeReg.exec(value);
  215 + ctx.setFontSize(match[1]);
  216 + return;
  217 + }
  218 + // #endif
  219 +
  220 + if (style === 'opacity') {
  221 + ctx.setGlobalAlpha(value)
  222 + return;
  223 + }
  224 + if (style !== 'fillStyle' && style !== 'strokeStyle' || value !== 'none' && value !== null) {
  225 + // #ifdef H5 || APP-PLUS || MP-BAIDU
  226 + if(typeof value == 'object') {
  227 + if (value.hasOwnProperty('colorStop') || value.hasOwnProperty('colors')) {
  228 + ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
  229 + }
  230 + return
  231 + }
  232 + // #endif
  233 + // #ifdef MP-TOUTIAO
  234 + if(colorReg.test(value)) {
  235 + value = value.replace(colorReg, '#$1$1$2$2$3$3')
  236 + }
  237 + // #endif
  238 + ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
  239 + }
  240 + }
  241 + });
  242 + });
  243 + if(!this.isNew && !child) {
  244 + ctx.uniDrawImage = ctx.drawImage
  245 + ctx.drawImage = (...a) => {
  246 + a[0] = a[0].src
  247 + ctx.uniDrawImage(...a)
  248 + }
  249 + }
  250 + if(!ctx.createRadialGradient) {
  251 + ctx.createRadialGradient = function() {
  252 + return ctx.createCircularGradient(...[...arguments].slice(-3))
  253 + };
  254 + }
  255 + // 字节不支持
  256 + if (!ctx.strokeText) {
  257 + ctx.strokeText = (...a) => {
  258 + ctx.fillText(...a)
  259 + }
  260 + }
  261 +
  262 + // 钉钉不支持 , 鸿蒙是异步
  263 + if (!ctx.measureText || uni.getSystemInfoSync().osName == 'harmonyos') {
  264 + ctx._measureText = ctx.measureText
  265 + const strLen = (str) => {
  266 + let len = 0;
  267 + for (let i = 0; i < str.length; i++) {
  268 + if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {
  269 + len++;
  270 + } else {
  271 + len += 2;
  272 + }
  273 + }
  274 + return len;
  275 + }
  276 + ctx.measureText = (text, font) => {
  277 + let fontSize = ctx?.state?.fontSize || 12;
  278 + if (font) {
  279 + fontSize = parseInt(font.match(/([\d\.]+)px/)[1])
  280 + }
  281 + fontSize /= 2;
  282 + let isBold = fontSize >= 16;
  283 + const widthFactor = isBold ? 1.3 : 1;
  284 + // ctx._measureText(text, (res) => {})
  285 + return {
  286 + width: strLen(text) * fontSize * widthFactor
  287 + };
  288 + }
  289 + }
  290 + }
  291 +
  292 + _initEvent(e) {
  293 + this.event = {};
  294 + const eventNames = [{
  295 + wxName: 'touchStart',
  296 + ecName: 'mousedown'
  297 + }, {
  298 + wxName: 'touchMove',
  299 + ecName: 'mousemove'
  300 + }, {
  301 + wxName: 'touchEnd',
  302 + ecName: 'mouseup'
  303 + }, {
  304 + wxName: 'touchEnd',
  305 + ecName: 'click'
  306 + }];
  307 +
  308 + eventNames.forEach(name => {
  309 + this.event[name.wxName] = e => {
  310 + const touch = e.touches[0];
  311 + this.chart.getZr().handler.dispatch(name.ecName, {
  312 + zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
  313 + zrY: name.wxName === 'tap' ? touch.clientY : touch.y
  314 + });
  315 + };
  316 + });
  317 + }
  318 +
  319 + set width(w) {
  320 + this.canvasNode.width = w
  321 + }
  322 + set height(h) {
  323 + this.canvasNode.height = h
  324 + }
  325 +
  326 + get width() {
  327 + return this.canvasNode.width || 0
  328 + }
  329 + get height() {
  330 + return this.canvasNode.height || 0
  331 + }
  332 + get ctx() {
  333 + return cacheChart[this.canvasId]['ctx'] || null
  334 + }
  335 + set chart(chart) {
  336 + cacheChart[this.canvasId]['chart'] = chart
  337 + }
  338 + get chart() {
  339 + return cacheChart[this.canvasId]['chart'] || null
  340 + }
  341 +}
  342 +
  343 +export function dispatch(name, {x,y, wheelDelta}) {
  344 + this.dispatch(name, {
  345 + zrX: x,
  346 + zrY: y,
  347 + zrDelta: wheelDelta,
  348 + preventDefault: () => {},
  349 + stopPropagation: () =>{}
  350 + });
  351 +}
  352 +export function setCanvasCreator(echarts, {canvas, node}) {
  353 + // echarts.setCanvasCreator(() => canvas);
  354 + if(echarts && !echarts.registerPreprocessor) {
  355 + return console.warn('echarts 版本不对或未传入echarts,vue3请使用esm格式')
  356 + }
  357 + echarts.registerPreprocessor(option => {
  358 + if (option && option.series) {
  359 + if (option.series.length > 0) {
  360 + option.series.forEach(series => {
  361 + series.progressive = 0;
  362 + });
  363 + } else if (typeof option.series === 'object') {
  364 + option.series.progressive = 0;
  365 + }
  366 + }
  367 + });
  368 + function loadImage(src, onload, onerror) {
  369 + let img = null
  370 + if(node && node.createImage) {
  371 + img = node.createImage()
  372 + img.onload = onload.bind(img);
  373 + img.onerror = onerror.bind(img);
  374 + img.src = src;
  375 + return img
  376 + } else {
  377 + img = new Image()
  378 + img.onload = onload.bind(img)
  379 + img.onerror = onerror.bind(img);
  380 + img.src = src
  381 + return img
  382 + }
  383 + }
  384 + if(echarts.setPlatformAPI) {
  385 + echarts.setPlatformAPI({
  386 + loadImage: canvas.setChart ? loadImage : null,
  387 + createCanvas(){
  388 + const key = 'createOffscreenCanvas'
  389 + return uni.canIUse(key) && uni[key] ? uni[key]({type: '2d'}) : canvas
  390 + }
  391 + })
  392 + }
  393 +}
\ No newline at end of file
... ...
  1 +<template>
  2 + <!-- #ifdef APP -->
  3 + <web-view class="lime-echart" ref="chartRef" @load="loaded" :style="[customStyle]"
  4 + :webview-styles="[webviewStyles]" src="/uni_modules/lime-echart/static/uvue.html?v=10112">
  5 + </web-view>
  6 + <!-- #endif -->
  7 + <!-- #ifdef H5 -->
  8 + <div class="lime-echart" ref="chartRef"></div>
  9 + <!-- #endif -->
  10 +</template>
  11 +
  12 +<script lang="uts" setup>
  13 + // @ts-nocheck
  14 + import { Echarts } from './uvue';
  15 + type EchartsResolve = (value : Echarts) => void
  16 + defineOptions({
  17 + name: 'l-echart'
  18 + })
  19 + const emits = defineEmits(['finished'])
  20 + const props = defineProps({
  21 + // #ifdef APP
  22 + webviewStyles: {
  23 + type: Object
  24 + },
  25 + customStyle: {
  26 + type: Object
  27 + },
  28 + // #endif
  29 + // #ifndef APP
  30 + webviewStyles: {
  31 + type: Object
  32 + },
  33 + customStyle: {
  34 + type: [String, Object]
  35 + },
  36 + // #endif
  37 + isDisableScroll: {
  38 + type: Boolean,
  39 + default: false
  40 + },
  41 + isClickable: {
  42 + type: Boolean,
  43 + default: true
  44 + },
  45 + enableHover: {
  46 + type: Boolean,
  47 + default: false
  48 + },
  49 + beforeDelay: {
  50 + type: Number,
  51 + default: 30
  52 + }
  53 + })
  54 +
  55 + const finished = ref(false)
  56 + const map = [] as EchartsResolve[]
  57 + const callbackMap = [] as EchartsResolve[]
  58 + // let context = null as UniWebViewElement | null
  59 + let chart = null as Echarts | null
  60 + let chartRef = ref<UniWebViewElement | null>(null)
  61 +
  62 + const trigger = () => {
  63 + // #ifdef APP
  64 + if (finished.value) {
  65 + if (chart == null) {
  66 + chart = new Echarts(chartRef.value!)
  67 + }
  68 + while (map.length > 0) {
  69 + const resolve = map.pop() as EchartsResolve
  70 + resolve(chart!)
  71 + }
  72 + }
  73 + // #endif
  74 + // #ifdef H5
  75 + while (map.length > 0) {
  76 + if(chart != null){
  77 + const resolve = map.pop() as EchartsResolve
  78 + resolve(chart!)
  79 + }
  80 + }
  81 + // #endif
  82 +
  83 + if(chart != null){
  84 + while(callbackMap.length > 0){
  85 + const callback = callbackMap.pop() as EchartsResolve
  86 + callback(chart!)
  87 + }
  88 + }
  89 + }
  90 +
  91 + // #ifdef APP
  92 + const loaded = (event : UniWebViewLoadEvent) => {
  93 + event.stopPropagation()
  94 + event.preventDefault()
  95 + finished.value = true
  96 + trigger()
  97 + emits('finished')
  98 + }
  99 + // #endif
  100 +
  101 +
  102 + const _next = () : boolean => {
  103 + if (chart == null) {
  104 + console.warn(`组件还未初始化,请先使用 init`)
  105 + return true
  106 + }
  107 + return false
  108 + }
  109 + const setOption = (option : UTSJSONObject) => {
  110 + if (_next()) return
  111 + chart!.setOption(option);
  112 + }
  113 + const showLoading = () => {
  114 + if (_next()) return
  115 + chart!.showLoading();
  116 + }
  117 + const hideLoading = () => {
  118 + if (_next()) return
  119 + chart!.hideLoading();
  120 + }
  121 + const clear = () => {
  122 + if (_next()) return
  123 + chart!.clear();
  124 + }
  125 + const dispose = () => {
  126 + if (_next()) return
  127 + chart!.dispose();
  128 + }
  129 + const resize = (size : UTSJSONObject) => {
  130 + if (_next()) return
  131 + chart!.resize(size);
  132 + }
  133 + const canvasToTempFilePath = (opt : UTSJSONObject) => {
  134 + if (_next()) return
  135 + chart!.canvasToTempFilePath(opt);
  136 + }
  137 + // function init() : Promise<Echarts> {
  138 + // return new Promise((resolve) => {
  139 + // map.push(resolve)
  140 + // trigger()
  141 + // })
  142 + // }
  143 + // #ifdef APP
  144 + function init(callback : ((chart : Echarts) => void) | null) : Promise<Echarts> {
  145 + // if (chart !== null && callback != null) {
  146 + // callback(chart!)
  147 + // } else {
  148 + // console.warn('echarts 未加载完成,您可以延时一下')
  149 + // }
  150 + if(callback!=null){
  151 + callbackMap.push(callback)
  152 + }
  153 + return new Promise<Echarts>((resolve) => {
  154 + map.push(resolve)
  155 + trigger()
  156 + })
  157 + }
  158 + // #endif
  159 + // #ifdef H5
  160 + const touchstart = (e) => {
  161 + if(chart == null) return
  162 + const handler = chart.getZr().handler;
  163 + const rect = chart.getZr().dom.getBoundingClientRect()
  164 + handler.dispatch('mousedown', {
  165 + zrX: e.touches[0].clientX - rect.left,
  166 + zrY: e.touches[0].clientY - rect.top
  167 + })
  168 + handler.dispatch('click', {
  169 + zrX: e.touches[0].clientX - rect.left,
  170 + zrY: e.touches[0].clientY - rect.top
  171 + })
  172 + }
  173 + const touchmove = (e) => {
  174 + if(chart == null) return
  175 + const handler = chart.getZr().handler;
  176 + const rect = chart.getZr().dom.getBoundingClientRect()
  177 + handler.dispatch('mousemove', {
  178 + zrX: e.touches[0].clientX - rect.left,
  179 + zrY: e.touches[0].clientY - rect.top
  180 + })
  181 + }
  182 + const mouseup = (e) => {
  183 + if(chart == null) return
  184 + const handler = chart.getZr().handler;
  185 + handler.dispatch('mousemove', {
  186 + zrX: 999999999,
  187 + zrY: 999999999
  188 + })
  189 + handler.dispatch('mouseup', {
  190 + zrX: 999999999,
  191 + zrY: 999999999
  192 + })
  193 + }
  194 + function init(echarts: any, ...args: any[]): Promise<Echarts>{
  195 + if(echarts == null){
  196 + console.error('请确保已经引入了 ECharts 库');
  197 + return Promise.reject('请确保已经引入了 ECharts 库');
  198 + }
  199 + let theme:string|null=null
  200 + let opts={}
  201 + let callback:Function|null=null;
  202 +
  203 + args.forEach(item =>{
  204 + if(typeof item === 'function') {
  205 + callback = item
  206 + } else if(['string'].includes(typeof item)){
  207 + theme = item
  208 + } else if(typeof item === 'object'){
  209 + opts = item
  210 + }
  211 + })
  212 + chart = echarts.init(chartRef.value, theme, opts)
  213 + window.addEventListener('touchstart', touchstart)
  214 + window.addEventListener('touchmove', touchmove)
  215 + window.addEventListener('touchend', mouseup)
  216 +
  217 + if(callback!=null && typeof callback == 'function'){
  218 + callbackMap.push(callback)
  219 + }
  220 + return new Promise<Echarts>((resolve) => {
  221 + map.push(resolve)
  222 + trigger()
  223 + })
  224 + }
  225 + onMounted(()=>{
  226 + finished.value = true
  227 + trigger()
  228 + emits('finished')
  229 + })
  230 + onUnmounted(()=>{
  231 + window.removeEventListener('touchstart', touchstart)
  232 + window.removeEventListener('touchmove', touchmove)
  233 + window.removeEventListener('touchend', mouseup)
  234 + })
  235 + // #endif
  236 +
  237 + defineExpose({
  238 + init,
  239 + setOption,
  240 + showLoading,
  241 + hideLoading,
  242 + clear,
  243 + dispose,
  244 + resize,
  245 + canvasToTempFilePath
  246 + })
  247 +</script>
  248 +<style lang="scss">
  249 + .lime-echart {
  250 + flex: 1;
  251 + }
  252 +</style>
\ No newline at end of file
... ...
  1 +<template>
  2 + <view class="lime-echart" :style="customStyle" v-if="canvasId" ref="limeEchart" :aria-label="ariaLabel">
  3 + <!-- #ifndef APP-NVUE -->
  4 + <canvas
  5 + class="lime-echart__canvas"
  6 + v-if="use2dCanvas"
  7 + type="2d"
  8 + :id="canvasId"
  9 + :style="canvasStyle"
  10 + :disable-scroll="isDisableScroll"
  11 + @touchstart="touchStart"
  12 + @touchmove="touchMove"
  13 + @touchend="touchEnd"
  14 + />
  15 + <canvas
  16 + class="lime-echart__canvas"
  17 + v-else
  18 + :width="nodeWidth"
  19 + :height="nodeHeight"
  20 + :style="canvasStyle"
  21 + :canvas-id="canvasId"
  22 + :id="canvasId"
  23 + :disable-scroll="isDisableScroll"
  24 + @touchstart="touchStart"
  25 + @touchmove="touchMove"
  26 + @touchend="touchEnd"
  27 + />
  28 + <view class="lime-echart__mask"
  29 + v-if="isPC"
  30 + @mousedown="touchStart"
  31 + @mousemove="touchMove"
  32 + @mouseup="touchEnd"
  33 + @touchstart="touchStart"
  34 + @touchmove="touchMove"
  35 + @touchend="touchEnd">
  36 + </view>
  37 + <canvas v-if="isOffscreenCanvas" :style="offscreenStyle" :canvas-id="offscreenCanvasId"></canvas>
  38 + <!-- #endif -->
  39 + <!-- #ifdef APP-NVUE -->
  40 + <web-view
  41 + class="lime-echart__canvas"
  42 + :id="canvasId"
  43 + :style="canvasStyle"
  44 + :webview-styles="webviewStyles"
  45 + ref="webview"
  46 + src="/uni_modules/lime-echart/static/uvue.html?v=1"
  47 + @pagefinish="finished = true"
  48 + @onPostMessage="onMessage"
  49 + ></web-view>
  50 + <!-- #endif -->
  51 + </view>
  52 +</template>
  53 +
  54 +<script>
  55 +// #ifndef APP-NVUE
  56 +import {Canvas, setCanvasCreator, dispatch} from './canvas';
  57 +import {wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect} from './utils';
  58 +// #endif
  59 +// #ifdef APP-NVUE
  60 +import { base64ToPath, sleep } from './utils';
  61 +import {Echarts} from './nvue'
  62 +// #endif
  63 +const charts = {}
  64 +const echartsObj = {}
  65 +
  66 +
  67 +/**
  68 + * LimeChart 图表
  69 + * @description 全端兼容的eCharts
  70 + * @tutorial https://ext.dcloud.net.cn/plugin?id=4899
  71 +
  72 + * @property {String} customStyle 自定义样式
  73 + * @property {String} type 指定 canvas 类型
  74 + * @value 2d 使用canvas 2d,部分小程序支持
  75 + * @value '' 使用原生canvas,会有层级问题
  76 + * @value bottom right 不缩放图片,只显示图片的右下边区域
  77 + * @property {Boolean} isDisableScroll
  78 + * @property {number} beforeDelay = [30] 延迟初始化 (毫秒)
  79 + * @property {Boolean} enableHover PC端使用鼠标悬浮
  80 +
  81 + * @event {Function} finished 加载完成触发
  82 + */
  83 +export default {
  84 + name: 'lime-echart',
  85 + props: {
  86 + // #ifdef MP-WEIXIN || MP-TOUTIAO
  87 + type: {
  88 + type: String,
  89 + default: '2d'
  90 + },
  91 + // #endif
  92 + // #ifdef APP-NVUE
  93 + webviewStyles: Object,
  94 + // hybrid: Boolean,
  95 + // #endif
  96 + customStyle: String,
  97 + isDisableScroll: Boolean,
  98 + isClickable: {
  99 + type: Boolean,
  100 + default: true
  101 + },
  102 + enableHover: Boolean,
  103 + beforeDelay: {
  104 + type: Number,
  105 + default: 30
  106 + }
  107 + },
  108 + data() {
  109 + return {
  110 + // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
  111 + use2dCanvas: true,
  112 + // #endif
  113 + // #ifndef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
  114 + use2dCanvas: false,
  115 + // #endif
  116 + ariaLabel: '图表',
  117 + width: null,
  118 + height: null,
  119 + nodeWidth: null,
  120 + nodeHeight: null,
  121 + // canvasNode: null,
  122 + config: {},
  123 + inited: false,
  124 + finished: false,
  125 + file: '',
  126 + platform: '',
  127 + isPC: false,
  128 + isDown: false,
  129 + isOffscreenCanvas: false,
  130 + offscreenWidth: 0,
  131 + offscreenHeight: 0
  132 + };
  133 + },
  134 + computed: {
  135 + canvasId() {
  136 + return `lime-echart${this._ && this._.uid || this._uid}`
  137 + },
  138 + offscreenCanvasId() {
  139 + return `${this.canvasId}_offscreen`
  140 + },
  141 + offscreenStyle() {
  142 + return `width:${this.offscreenWidth}px;height: ${this.offscreenHeight}px; position: fixed; left: 99999px; background: red`
  143 + },
  144 + canvasStyle() {
  145 + return this.width && this.height ? ('width:' + this.width + 'px;height:' + this.height + 'px') : ''
  146 + }
  147 + },
  148 + // #ifndef VUE3
  149 + beforeDestroy() {
  150 + this.clear()
  151 + this.dispose()
  152 + // #ifdef H5
  153 + if(this.isPC) {
  154 + document.removeEventListener('mousewheel', this.mousewheel)
  155 + }
  156 + // #endif
  157 + },
  158 + // #endif
  159 + // #ifdef VUE3
  160 + beforeUnmount() {
  161 + this.clear()
  162 + this.dispose()
  163 + // #ifdef H5
  164 + if(this.isPC) {
  165 + document.removeEventListener('mousewheel', this.mousewheel)
  166 + }
  167 + // #endif
  168 + },
  169 + // #endif
  170 + created() {
  171 + // #ifdef H5
  172 + if(!('ontouchstart' in window)) {
  173 + this.isPC = true
  174 + document.addEventListener('mousewheel', this.mousewheel)
  175 + }
  176 + // #endif
  177 + // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
  178 + const { platform } = uni.getSystemInfoSync();
  179 + this.isPC = /windows/i.test(platform)
  180 + // #endif
  181 + this.use2dCanvas = this.type === '2d' && canIUseCanvas2d()
  182 + },
  183 + mounted() {
  184 + this.$nextTick(() => {
  185 + this.$emit('finished')
  186 + })
  187 + },
  188 + methods: {
  189 + // #ifdef APP-NVUE
  190 + onMessage(e) {
  191 + const detail = e?.detail?.data[0] || null;
  192 + const data = detail?.data
  193 + const key = detail?.event
  194 + const options = data?.options
  195 + const event = data?.event
  196 + const file = detail?.file
  197 + if (key == 'log' && data) {
  198 + console.log(data)
  199 + }
  200 + if(event) {
  201 + this.chart.dispatchAction(event.replace(/"/g,''), options)
  202 + }
  203 + if(file) {
  204 + thie.file = file
  205 + }
  206 + },
  207 + // #endif
  208 + setChart(callback) {
  209 + if(!this.chart) {
  210 + console.warn(`组件还未初始化,请先使用 init`)
  211 + return
  212 + }
  213 + if(typeof callback === 'function' && this.chart) {
  214 + callback(this.chart);
  215 + }
  216 + // #ifdef APP-NVUE
  217 + if(typeof callback === 'function') {
  218 + this.$refs.webview.evalJs(`setChart(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.chart.options)})`);
  219 + }
  220 + // #endif
  221 + },
  222 + setOption() {
  223 + if (!this.chart || !this.chart.setOption) {
  224 + console.warn(`组件还未初始化,请先使用 init`)
  225 + return
  226 + }
  227 + this.chart.setOption(...arguments);
  228 + },
  229 + showLoading() {
  230 + if(this.chart) {
  231 + this.chart.showLoading(...arguments)
  232 + }
  233 + },
  234 + hideLoading() {
  235 + if(this.chart) {
  236 + this.chart.hideLoading()
  237 + }
  238 + },
  239 + clear() {
  240 + if(this.chart) {
  241 + this.chart.clear()
  242 + }
  243 + },
  244 + dispose() {
  245 + if(this.chart) {
  246 + this.chart.dispose()
  247 + }
  248 + },
  249 + resize(size) {
  250 + if(size && size.width && size.height) {
  251 + this.height = size.height
  252 + this.width = size.width
  253 + if(this.chart) {this.chart.resize(size)}
  254 + } else {
  255 + this.$nextTick(() => {
  256 + uni.createSelectorQuery()
  257 + .in(this)
  258 + .select(`.lime-echart`)
  259 + .boundingClientRect()
  260 + .exec(res => {
  261 + if (res) {
  262 + let { width, height } = res[0];
  263 + this.width = width = width || 300;
  264 + this.height = height = height || 300;
  265 + this.chart.resize({width, height})
  266 + }
  267 + });
  268 + })
  269 +
  270 + }
  271 +
  272 + },
  273 + canvasToTempFilePath(args = {}) {
  274 + // #ifndef APP-NVUE
  275 + const { use2dCanvas, canvasId } = this;
  276 + return new Promise((resolve, reject) => {
  277 + const copyArgs = Object.assign({
  278 + canvasId,
  279 + success: resolve,
  280 + fail: reject
  281 + }, args);
  282 + if (use2dCanvas) {
  283 + delete copyArgs.canvasId;
  284 + copyArgs.canvas = this.canvasNode;
  285 + }
  286 + uni.canvasToTempFilePath(copyArgs, this);
  287 + });
  288 + // #endif
  289 + // #ifdef APP-NVUE
  290 + this.file = ''
  291 + this.$refs.webview.evalJs(`canvasToTempFilePath()`);
  292 + return new Promise((resolve, reject) => {
  293 + this.$watch('file', async (file) => {
  294 + if(file) {
  295 + const tempFilePath = await base64ToPath(file)
  296 + resolve(args.success({tempFilePath}))
  297 + } else {
  298 + reject(args.fail({error: ``}))
  299 + }
  300 + })
  301 + })
  302 + // #endif
  303 + },
  304 + async init(echarts, ...args) {
  305 + // #ifndef APP-NVUE
  306 + if(args && args.length == 0 && !echarts) {
  307 + console.error('缺少参数:init(echarts, theme?:string, opts?: object, callback?: function)')
  308 + return
  309 + }
  310 + // #endif
  311 + let theme=null,opts={},callback;
  312 +
  313 + Array.from(arguments).forEach(item => {
  314 + if(typeof item === 'function') {
  315 + callback = item
  316 + }
  317 + if(['string'].includes(typeof item)) {
  318 + theme = item
  319 + }
  320 + if(typeof item === 'object') {
  321 + opts = item
  322 + }
  323 + })
  324 +
  325 + if(this.beforeDelay) {
  326 + await sleep(this.beforeDelay)
  327 + }
  328 + let config = await this.getContext();
  329 + // #ifndef APP-NVUE
  330 + setCanvasCreator(echarts, config)
  331 + try {
  332 + this.chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
  333 + if(typeof callback === 'function') {
  334 + callback(this.chart)
  335 + } else {
  336 + return this.chart
  337 + }
  338 + } catch(e) {
  339 + console.error(e.messges)
  340 + return null
  341 + }
  342 + // #endif
  343 + // #ifdef APP-NVUE
  344 + this.chart = new Echarts(this.$refs.webview)
  345 + this.$refs.webview.evalJs(`init(null, null, ${JSON.stringify(opts)}, ${theme})`)
  346 + if(callback) {
  347 + callback(this.chart)
  348 + } else {
  349 + return this.chart
  350 + }
  351 + // #endif
  352 + },
  353 + getContext() {
  354 + // #ifdef APP-NVUE
  355 + if(this.finished) {
  356 + return Promise.resolve(this.finished)
  357 + }
  358 + return new Promise(resolve => {
  359 + this.$watch('finished', (val) => {
  360 + if(val) {
  361 + resolve(this.finished)
  362 + }
  363 + })
  364 + })
  365 + // #endif
  366 + // #ifndef APP-NVUE
  367 + return getRect(`#${this.canvasId}`, {context: this, type: this.use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {
  368 + if(res) {
  369 + let dpr = devicePixelRatio
  370 + let {width, height, node} = res
  371 + let canvas;
  372 + this.width = width = width || 300;
  373 + this.height = height = height || 300;
  374 + if(node) {
  375 + const ctx = node.getContext('2d');
  376 + canvas = new Canvas(ctx, this, true, node);
  377 + this.canvasNode = node
  378 + } else {
  379 + // #ifdef MP-TOUTIAO
  380 + dpr = !this.isPC ? devicePixelRatio : 1// 1.25
  381 + // #endif
  382 + // #ifndef MP-ALIPAY || MP-TOUTIAO
  383 + dpr = this.isPC ? devicePixelRatio : 1
  384 + // #endif
  385 + // #ifdef MP-ALIPAY || MP-LARK
  386 + dpr = devicePixelRatio
  387 + // #endif
  388 + // #ifdef WEB
  389 + dpr = 1
  390 + // #endif
  391 + this.rect = res
  392 + this.nodeWidth = width * dpr;
  393 + this.nodeHeight = height * dpr;
  394 + const ctx = uni.createCanvasContext(this.canvasId, this);
  395 + canvas = new Canvas(ctx, this, false);
  396 + }
  397 + return { canvas, width, height, devicePixelRatio: dpr, node };
  398 + } else {
  399 + return {}
  400 + }
  401 + })
  402 + // #endif
  403 + },
  404 + // #ifndef APP-NVUE
  405 + getRelative(e, touches) {
  406 + let { clientX, clientY } = e
  407 + if(!(clientX && clientY) && touches && touches[0]) {
  408 + clientX = touches[0].clientX
  409 + clientY = touches[0].clientY
  410 + }
  411 + return {x: clientX - this.rect.left, y: clientY - this.rect.top, wheelDelta: e.wheelDelta || 0}
  412 + },
  413 + getTouch(e, touches) {
  414 + const {x} = touches && touches[0] || {}
  415 + return x ? touches[0] : this.getRelative(e, touches);
  416 + },
  417 + touchStart(e) {
  418 + this.isDown = true
  419 + const next = () => {
  420 + const touches = convertTouchesToArray(e.touches)
  421 + if(this.chart) {
  422 + const touch = this.getTouch(e, touches)
  423 + this.startX = touch.x
  424 + this.startY = touch.y
  425 + this.startT = new Date()
  426 + const handler = this.chart.getZr().handler;
  427 + dispatch.call(handler, 'mousedown', touch)
  428 + dispatch.call(handler, 'mousemove', touch)
  429 + handler.processGesture(wrapTouch(e), 'start');
  430 + clearTimeout(this.endTimer);
  431 + }
  432 +
  433 + }
  434 + if(this.isPC) {
  435 + getRect(`#${this.canvasId}`, {context: this}).then(res => {
  436 + this.rect = res
  437 + next()
  438 + })
  439 + return
  440 + }
  441 + next()
  442 + },
  443 + touchMove(e) {
  444 + if(this.isPC && this.enableHover && !this.isDown) {this.isDown = true}
  445 + const touches = convertTouchesToArray(e.touches)
  446 + if (this.chart && this.isDown) {
  447 + const handler = this.chart.getZr().handler;
  448 + dispatch.call(handler, 'mousemove', this.getTouch(e, touches))
  449 + handler.processGesture(wrapTouch(e), 'change');
  450 + }
  451 +
  452 + },
  453 + touchEnd(e) {
  454 + this.isDown = false
  455 + if (this.chart) {
  456 + const touches = convertTouchesToArray(e.changedTouches)
  457 + const {x} = touches && touches[0] || {}
  458 + const touch = (x ? touches[0] : this.getRelative(e, touches)) || {};
  459 + const handler = this.chart.getZr().handler;
  460 + const isClick = Math.abs(touch.x - this.startX) < 10 && new Date() - this.startT < 200;
  461 + dispatch.call(handler, 'mouseup', touch)
  462 + handler.processGesture(wrapTouch(e), 'end');
  463 + if(isClick) {
  464 + dispatch.call(handler, 'click', touch)
  465 + } else {
  466 + this.endTimer = setTimeout(() => {
  467 + dispatch.call(handler, 'mousemove', {x: 999999999,y: 999999999});
  468 + dispatch.call(handler, 'mouseup', {x: 999999999,y: 999999999});
  469 + },50)
  470 + }
  471 + }
  472 + },
  473 + // #endif
  474 + // #ifdef H5
  475 + mousewheel(e){
  476 + if(this.chart) {
  477 + dispatch.call(this.chart.getZr().handler, 'mousewheel', this.getTouch(e))
  478 + }
  479 + }
  480 + // #endif
  481 + }
  482 +};
  483 +</script>
  484 +<style>
  485 +.lime-echart {
  486 + position: relative;
  487 + /* #ifndef APP-NVUE */
  488 + width: 100%;
  489 + height: 100%;
  490 + /* #endif */
  491 + /* #ifdef APP-NVUE */
  492 + flex: 1;
  493 + /* #endif */
  494 +}
  495 +.lime-echart__canvas {
  496 + /* #ifndef APP-NVUE */
  497 + width: 100%;
  498 + height: 100%;
  499 + /* #endif */
  500 + /* #ifdef APP-NVUE */
  501 + flex: 1;
  502 + /* #endif */
  503 +}
  504 +/* #ifndef APP-NVUE */
  505 +.lime-echart__mask {
  506 + position: absolute;
  507 + width: 100%;
  508 + height: 100%;
  509 + left: 0;
  510 + top: 0;
  511 + z-index: 1;
  512 +}
  513 +/* #endif */
  514 +</style>
... ...
  1 +export class Echarts {
  2 + eventMap = new Map()
  3 + constructor(webview) {
  4 + this.webview = webview
  5 + this.options = null
  6 + }
  7 + setOption() {
  8 + this.options = arguments
  9 + this.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
  10 + }
  11 + getOption() {
  12 + return this.options
  13 + }
  14 + showLoading() {
  15 + this.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
  16 + }
  17 + hideLoading() {
  18 + this.webview.evalJs(`hideLoading()`);
  19 + }
  20 + clear() {
  21 + this.webview.evalJs(`clear()`);
  22 + }
  23 + dispose() {
  24 + this.webview.evalJs(`dispose()`);
  25 + }
  26 + resize(size) {
  27 + if(size) {
  28 + this.webview.evalJs(`resize(${JSON.stringify(size)})`);
  29 + } else {
  30 + this.webview.evalJs(`resize()`);
  31 + }
  32 + }
  33 + on(type, ...args) {
  34 + const query = args[0]
  35 + const useQuery = query && typeof query != 'function'
  36 + const param = useQuery ? [type, query] : [type]
  37 + const key = `${type}${useQuery ? JSON.stringify(query): '' }`
  38 + const callback = useQuery ? args[1]: args[0]
  39 + if(typeof callback == 'function'){
  40 + this.eventMap.set(key, callback)
  41 + }
  42 + this.webview.evalJs(`on(${JSON.stringify(param)})`);
  43 + console.warn('nvue 暂不支持事件')
  44 + }
  45 + dispatchAction(type, options){
  46 + const handler = this.eventMap.get(type)
  47 + if(handler){
  48 + handler(options)
  49 + }
  50 + }
  51 +}
\ No newline at end of file
... ...
  1 +// #ifndef APP-NVUE
  2 +// 计算版本
  3 +export function compareVersion(v1, v2) {
  4 + v1 = v1.split('.')
  5 + v2 = v2.split('.')
  6 + const len = Math.max(v1.length, v2.length)
  7 + while (v1.length < len) {
  8 + v1.push('0')
  9 + }
  10 + while (v2.length < len) {
  11 + v2.push('0')
  12 + }
  13 + for (let i = 0; i < len; i++) {
  14 + const num1 = parseInt(v1[i], 10)
  15 + const num2 = parseInt(v2[i], 10)
  16 +
  17 + if (num1 > num2) {
  18 + return 1
  19 + } else if (num1 < num2) {
  20 + return -1
  21 + }
  22 + }
  23 + return 0
  24 +}
  25 +const systemInfo = uni.getSystemInfoSync();
  26 +
  27 +function gte(version) {
  28 + // 截止 2023-03-22 mac pc小程序不支持 canvas 2d
  29 + let {
  30 + SDKVersion,
  31 + platform
  32 + } = systemInfo;
  33 + // #ifdef MP-ALIPAY
  34 + SDKVersion = my.SDKVersion
  35 + // #endif
  36 + // #ifdef MP-WEIXIN
  37 + return platform !== 'mac' && compareVersion(SDKVersion, version) >= 0;
  38 + // #endif
  39 + return compareVersion(SDKVersion, version) >= 0;
  40 +}
  41 +
  42 +
  43 +export function canIUseCanvas2d() {
  44 + // #ifdef MP-WEIXIN
  45 + return gte('2.9.0');
  46 + // #endif
  47 + // #ifdef MP-ALIPAY
  48 + return gte('2.7.0');
  49 + // #endif
  50 + // #ifdef MP-TOUTIAO
  51 + return gte('1.78.0');
  52 + // #endif
  53 + return false
  54 +}
  55 +
  56 +export function convertTouchesToArray(touches) {
  57 + // 如果 touches 是一个数组,则直接返回它
  58 + if (Array.isArray(touches)) {
  59 + return touches;
  60 + }
  61 + // 如果touches是一个对象,则转换为数组
  62 + if (typeof touches === 'object' && touches !== null) {
  63 + return Object.values(touches);
  64 + }
  65 + // 对于其他类型,直接返回它
  66 + return touches;
  67 +}
  68 +
  69 +export function wrapTouch(event) {
  70 + for (let i = 0; i < event.touches.length; ++i) {
  71 + const touch = event.touches[i];
  72 + touch.offsetX = touch.x;
  73 + touch.offsetY = touch.y;
  74 + }
  75 + return event;
  76 +}
  77 +export const devicePixelRatio = uni.getSystemInfoSync().pixelRatio
  78 +// #endif
  79 +// #ifdef APP-NVUE
  80 +export function base64ToPath(base64) {
  81 + return new Promise((resolve, reject) => {
  82 + const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
  83 + const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
  84 + bitmap.loadBase64Data(base64, () => {
  85 + if (!format) {
  86 + reject(new Error('ERROR_BASE64SRC_PARSE'))
  87 + }
  88 + const time = new Date().getTime();
  89 + const filePath = `_doc/uniapp_temp/${time}.${format}`
  90 +
  91 + bitmap.save(filePath, {},
  92 + () => {
  93 + bitmap.clear()
  94 + resolve(filePath)
  95 + },
  96 + (error) => {
  97 + bitmap.clear()
  98 + console.error(`${JSON.stringify(error)}`)
  99 + reject(error)
  100 + })
  101 + }, (error) => {
  102 + bitmap.clear()
  103 + console.error(`${JSON.stringify(error)}`)
  104 + reject(error)
  105 + })
  106 + })
  107 +}
  108 +// #endif
  109 +
  110 +
  111 +export function sleep(time) {
  112 + return new Promise((resolve) => {
  113 + setTimeout(() => {
  114 + resolve(true)
  115 + }, time)
  116 + })
  117 +}
  118 +
  119 +
  120 +export function getRect(selector, options = {}) {
  121 + const typeDefault = 'boundingClientRect'
  122 + const {
  123 + context,
  124 + type = typeDefault
  125 + } = options
  126 + return new Promise((resolve, reject) => {
  127 + const dom = uni.createSelectorQuery().in(context).select(selector);
  128 + const result = (rect) => {
  129 + if (rect) {
  130 + resolve(rect)
  131 + } else {
  132 + reject()
  133 + }
  134 + }
  135 + if (type == typeDefault) {
  136 + dom[type](result).exec()
  137 + } else {
  138 + dom[type]({
  139 + node: true,
  140 + size: true,
  141 + rect: true
  142 + }, result).exec()
  143 + }
  144 + });
  145 +};
\ No newline at end of file
... ...
  1 +// @ts-nocheck
  2 +// #ifdef APP
  3 +type EchartsEventHandler = (event: UTSJSONObject)=>void
  4 +// type EchartsTempResolve = (obj : UTSJSONObject) => void
  5 +// type EchartsTempOptions = UTSJSONObject
  6 +export class Echarts {
  7 + options: UTSJSONObject = {} as UTSJSONObject
  8 + context: UniWebViewElement
  9 + eventMap: Map<string, EchartsEventHandler> = new Map()
  10 + private temp: UTSJSONObject[] = []
  11 + constructor(context: UniWebViewElement){
  12 + this.context = context
  13 + this.init()
  14 + }
  15 + init(){
  16 + this.context.evalJS(`init(null, null, ${JSON.stringify({})})`)
  17 +
  18 + this.context.addEventListener('message', (e : UniWebViewMessageEvent) => {
  19 + // event.stopPropagation()
  20 + // event.preventDefault()
  21 +
  22 + const detail = e.detail.data[0]
  23 + const file = detail.getString('file')
  24 + const data = detail.get('data')
  25 + const key = detail.getString('event')
  26 + const options = typeof data == 'object' ? (data as UTSJSONObject).getJSON('options'): null
  27 + const event = typeof data == 'object' ? (data as UTSJSONObject).getString('event'): null
  28 + if (key == 'log' && data != null) {
  29 + console.log(data)
  30 + }
  31 + if (event != null && options != null) {
  32 + this.dispatchAction(event.replace(/"/g,''), options)
  33 + }
  34 + if(file != null){
  35 + while (this.temp.length > 0) {
  36 + const opt = this.temp.pop()
  37 + const success = opt?.get('success')
  38 + if(typeof success == 'function'){
  39 + success as (res: UTSJSONObject) => void
  40 + success({tempFilePath: file})
  41 + }
  42 + }
  43 + }
  44 +
  45 + })
  46 + }
  47 + setOption(option: UTSJSONObject){
  48 + this.options = option;
  49 + this.context.evalJS(`setOption(${JSON.stringify([option])})`)
  50 + }
  51 + setOption(option: UTSJSONObject, notMerge: boolean = false, lazyUpdate: boolean = false){
  52 + this.options = option;
  53 + this.context.evalJS(`setOption(${JSON.stringify([option, notMerge, lazyUpdate])})`)
  54 + }
  55 + setOption(option: UTSJSONObject, notMerge: UTSJSONObject){
  56 + this.options = option;
  57 + this.context.evalJS(`setOption(${JSON.stringify([option, notMerge])})`)
  58 + }
  59 + getOption(): UTSJSONObject {
  60 + return this.options
  61 + }
  62 + showLoading(){
  63 + this.context.evalJS(`showLoading(${JSON.stringify([] as any[])})`);
  64 + }
  65 + showLoading(type: string, opts: UTSJSONObject){
  66 + this.context.evalJS(`showLoading(${JSON.stringify([type, opts])})`);
  67 + }
  68 + hideLoading(){
  69 + this.context.evalJS(`hideLoading()`);
  70 + }
  71 + clear(){
  72 + this.context.evalJS(`clear()`);
  73 + }
  74 + dispose(){
  75 + this.context.evalJS(`dispose()`);
  76 + }
  77 + resize(size:UTSJSONObject){
  78 + setTimeout(()=>{
  79 + this.context.evalJS(`resize(${JSON.stringify(size)})`);
  80 + },0)
  81 + }
  82 + resize(){
  83 + setTimeout(()=>{
  84 + this.context.evalJS(`resize()`);
  85 + },10)
  86 +
  87 + }
  88 + on(type:string, query: any, callback: EchartsEventHandler) {
  89 + const key = `${type}${JSON.stringify(query)}`
  90 + if(typeof callback == 'function'){
  91 + this.eventMap.set(key, callback)
  92 + }
  93 + this.context.evalJS(`on(${JSON.stringify([type, query])})`);
  94 + console.warn('uvue 暂不支持事件')
  95 + }
  96 + on(type:string, callback: EchartsEventHandler) {
  97 + const key = `${type}`
  98 + if(typeof callback == 'function'){
  99 + this.eventMap.set(key, callback)
  100 + }
  101 + this.context.evalJS(`on(${JSON.stringify([type])})`);
  102 + console.warn('uvue 暂不支持事件')
  103 + }
  104 + dispatchAction(type:string, options: UTSJSONObject){
  105 + const handler = this.eventMap.get(type)
  106 + if(handler!=null){
  107 + handler(options)
  108 + }
  109 + }
  110 + canvasToTempFilePath(opt: UTSJSONObject){
  111 + // this.context.evalJS(`on(${JSON.stringify(opt)})`);
  112 + this.context.evalJS(`canvasToTempFilePath(${JSON.stringify(opt)})`);
  113 + this.temp.push(opt)
  114 + }
  115 +}
  116 +
  117 +// #endif
  118 +// #ifndef APP
  119 +export class Echarts {
  120 + constructor() {}
  121 + setOption(option: UTSJSONObject): void
  122 + isDisposed(): boolean;
  123 + clear(): void;
  124 + resize(size:UTSJSONObject): void;
  125 + resize(): void;
  126 + canvasToTempFilePath(opt : UTSJSONObject): void;
  127 + dispose(): void;
  128 + showLoading(cfg?: UTSJSONObject): void;
  129 + showLoading(name?: string, cfg?: UTSJSONObject): void;
  130 + hideLoading(): void;
  131 + getZr(): any
  132 +}
  133 +// #endif
\ No newline at end of file
... ...
  1 +<template>
  2 + <view class="uni-section">
  3 + <view class="uni-section-header" @click="onClick">
  4 + <view class="uni-section-header__decoration" v-if="type" :class="type" />
  5 + <slot v-else name="decoration"></slot>
  6 +
  7 + <view class="uni-section-header__content">
  8 + <text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text>
  9 + <text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text>
  10 + </view>
  11 +
  12 + <view class="uni-section-header__slot-right">
  13 + <slot name="right"></slot>
  14 + </view>
  15 + </view>
  16 +
  17 + <view class="uni-section-content" :style="{padding: _padding}">
  18 + <slot />
  19 + </view>
  20 + </view>
  21 +</template>
  22 +
  23 +<script>
  24 +
  25 + /**
  26 + * Section 标题栏
  27 + * @description 标题栏
  28 + * @property {String} type = [line|circle|square] 标题装饰类型
  29 + * @value line 竖线
  30 + * @value circle 圆形
  31 + * @value square 正方形
  32 + * @property {String} title 主标题
  33 + * @property {String} titleFontSize 主标题字体大小
  34 + * @property {String} titleColor 主标题字体颜色
  35 + * @property {String} subTitle 副标题
  36 + * @property {String} subTitleFontSize 副标题字体大小
  37 + * @property {String} subTitleColor 副标题字体颜色
  38 + * @property {String} padding 默认插槽 padding
  39 + */
  40 +
  41 + export default {
  42 + name: 'UniSection',
  43 + emits:['click'],
  44 + props: {
  45 + type: {
  46 + type: String,
  47 + default: ''
  48 + },
  49 + title: {
  50 + type: String,
  51 + required: true,
  52 + default: ''
  53 + },
  54 + titleFontSize: {
  55 + type: String,
  56 + default: '14px'
  57 + },
  58 + titleColor:{
  59 + type: String,
  60 + default: '#333'
  61 + },
  62 + subTitle: {
  63 + type: String,
  64 + default: ''
  65 + },
  66 + subTitleFontSize: {
  67 + type: String,
  68 + default: '12px'
  69 + },
  70 + subTitleColor: {
  71 + type: String,
  72 + default: '#999'
  73 + },
  74 + padding: {
  75 + type: [Boolean, String],
  76 + default: false
  77 + }
  78 + },
  79 + computed:{
  80 + _padding(){
  81 + if(typeof this.padding === 'string'){
  82 + return this.padding
  83 + }
  84 +
  85 + return this.padding?'10px':''
  86 + }
  87 + },
  88 + watch: {
  89 + title(newVal) {
  90 + if (uni.report && newVal !== '') {
  91 + uni.report('title', newVal)
  92 + }
  93 + }
  94 + },
  95 + methods: {
  96 + onClick() {
  97 + this.$emit('click')
  98 + }
  99 + }
  100 + }
  101 +</script>
  102 +<style lang="scss" >
  103 + $uni-primary: #2979ff !default;
  104 +
  105 + .uni-section {
  106 + background-color: #fff;
  107 + .uni-section-header {
  108 + position: relative;
  109 + /* #ifndef APP-NVUE */
  110 + display: flex;
  111 + /* #endif */
  112 + flex-direction: row;
  113 + align-items: center;
  114 + padding: 12px 10px;
  115 + font-weight: normal;
  116 +
  117 + &__decoration{
  118 + margin-right: 6px;
  119 + background-color: $uni-primary;
  120 + &.line {
  121 + width: 4px;
  122 + height: 12px;
  123 + border-radius: 10px;
  124 + }
  125 +
  126 + &.circle {
  127 + width: 8px;
  128 + height: 8px;
  129 + border-top-right-radius: 50px;
  130 + border-top-left-radius: 50px;
  131 + border-bottom-left-radius: 50px;
  132 + border-bottom-right-radius: 50px;
  133 + }
  134 +
  135 + &.square {
  136 + width: 8px;
  137 + height: 8px;
  138 + }
  139 + }
  140 +
  141 + &__content {
  142 + /* #ifndef APP-NVUE */
  143 + display: flex;
  144 + /* #endif */
  145 + flex-direction: column;
  146 + flex: 1;
  147 + color: #333;
  148 +
  149 + .distraction {
  150 + flex-direction: row;
  151 + align-items: center;
  152 + }
  153 + &-sub {
  154 + margin-top: 2px;
  155 + }
  156 + }
  157 +
  158 + &__slot-right{
  159 + font-size: 14px;
  160 + }
  161 + }
  162 +
  163 + .uni-section-content{
  164 + font-size: 14px;
  165 + }
  166 + }
  167 +</style>
... ...
  1 +// 应用全局配置
  2 +module.exports = {
  3 +
  4 + baseUrl: 'http://ft.wecando21cn.com/api',
  5 + // baseUrl: 'http://127.0.0.1:8085',
  6 + // 应用信息
  7 + appInfo: {
  8 + // 应用名称
  9 + name: "ERP移动版",
  10 + // 应用版本
  11 + version: "1.1.0",
  12 + // 应用logo
  13 + logo: "/static/logo.png",
  14 + // 官方网站
  15 + site_url: "",
  16 + // 政策协议
  17 + agreements: [{
  18 + title: "隐私政策",
  19 + url: "https://XX.vip/protocol.html"
  20 + },
  21 + {
  22 + title: "用户服务协议",
  23 + url: "https://XX.vip/protocol.html"
  24 + },
  25 + {
  26 + title: "CDERP 通用移动版",
  27 + url: "https://gitee.com/i-love-ai/xy-mobile-master"
  28 + }
  29 + ]
  30 + },
  31 +
  32 + loginInfo: {
  33 + userName: "1000@admin",
  34 + password: "admin",
  35 +
  36 + }
  37 +}
... ...
  1 +/**
  2 + * @description: Request result set
  3 + */
  4 +export enum ResultEnum {
  5 + SUCCESS = 200,
  6 + ERROR = -1,
  7 + TIMEOUT = 401,
  8 + TYPE = 'success',
  9 +}
  10 +
  11 +export enum ResponseEnum {
  12 + BLOB = 'BLOB',
  13 +}
  14 +/**
  15 + * @description: request method
  16 + */
  17 +export enum RequestEnum {
  18 + GET = 'GET',
  19 + POST = 'POST',
  20 + PUT = 'PUT',
  21 + DELETE = 'DELETE',
  22 +}
  23 +
  24 +/**
  25 + * @description: contentType
  26 + */
  27 +export enum ContentTypeEnum {
  28 + // json
  29 + JSON = 'application/json;charset=UTF-8',
  30 + // form-data qs
  31 + FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
  32 + // form-data upload
  33 + BLOB = 'multipart/form-data;charset=UTF-8',
  34 +}
... ...
  1 +import Vue from 'vue'
  2 +import App from './App'
  3 +import store from './store' // store
  4 +import plugins from './plugins' // plugins
  5 +import './permission' // permission
  6 +Vue.use(plugins)
  7 +
  8 +Vue.config.productionTip = false
  9 +Vue.prototype.$store = store
  10 +
  11 +App.mpType = 'app'
  12 +
  13 +const app = new Vue({
  14 + ...App
  15 +})
  16 +
  17 +app.$mount()
... ...
  1 +{
  2 + "name" : "星云erp",
  3 + "appid" : "__UNI__25A9D80",
  4 + "description" : "",
  5 + "versionName" : "1.1.0",
  6 + "versionCode" : "100",
  7 + "transformPx" : false,
  8 + "app-plus" : {
  9 + "usingComponents" : true,
  10 + "nvueCompiler" : "uni-app",
  11 + "splashscreen" : {
  12 + "alwaysShowBeforeRender" : true,
  13 + "waiting" : true,
  14 + "autoclose" : true,
  15 + "delay" : 0
  16 + },
  17 + "modules" : {},
  18 + "distribute" : {
  19 + "android" : {
  20 + "permissions" : [
  21 + "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
  22 + "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
  23 + "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
  24 + "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
  25 + "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
  26 + "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
  27 + "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
  28 + "<uses-permission android:name=\"android.permission.CAMERA\"/>",
  29 + "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
  30 + "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
  31 + "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
  32 + "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
  33 + "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
  34 + "<uses-feature android:name=\"android.hardware.camera\"/>",
  35 + "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
  36 + ]
  37 + },
  38 + "ios" : {},
  39 + "sdkConfigs" : {}
  40 + }
  41 + },
  42 + "quickapp" : {},
  43 + "mp-weixin" : {
  44 + "appid" : "wxba9c105a7f18ab44",
  45 + "setting" : {
  46 + "urlCheck" : false,
  47 + "es6" : false,
  48 + "minified" : true,
  49 + "postcss" : true
  50 + },
  51 + "optimization" : {
  52 + "subPackages" : true
  53 + },
  54 + "usingComponents" : true
  55 + },
  56 + "vueVersion" : "2",
  57 + "h5" : {
  58 + "template" : "static/index.html",
  59 + "devServer" : {
  60 + "port" : 9090,
  61 + "https" : false
  62 + },
  63 + "title" : "星云ERP",
  64 + "router" : {
  65 + "mode" : "hash",
  66 + "base" : "./"
  67 + }
  68 + }
  69 +}
... ...
  1 +{
  2 + "name": "xy-mobile-master",
  3 + "lockfileVersion": 3,
  4 + "requires": true,
  5 + "packages": {
  6 + "node_modules/echarts": {
  7 + "version": "5.5.1",
  8 + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.5.1.tgz",
  9 + "integrity": "sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==",
  10 + "dependencies": {
  11 + "tslib": "2.3.0",
  12 + "zrender": "5.6.0"
  13 + }
  14 + },
  15 + "node_modules/tslib": {
  16 + "version": "2.3.0",
  17 + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
  18 + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
  19 + },
  20 + "node_modules/zrender": {
  21 + "version": "5.6.0",
  22 + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.0.tgz",
  23 + "integrity": "sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==",
  24 + "dependencies": {
  25 + "tslib": "2.3.0"
  26 + }
  27 + }
  28 + }
  29 +}
... ...
  1 +This file contains the PGP keys of various developers.
  2 +Please don't use them for email unless you have to. Their main
  3 +purpose is code signing.
  4 +
  5 +Examples of importing this file in your keystore:
  6 + gpg --import KEYS.txt
  7 + (need pgp and other examples here)
  8 +
  9 +Examples of adding your key to this file:
  10 + pgp -kxa <your name> and append it to this file.
  11 + (pgpk -ll <your name> && pgpk -xa <your name>) >> this file.
  12 + (gpg --list-sigs <your name>
  13 + && gpg --armor --export <your name>) >> this file.
  14 +
  15 +---------------------------------------
  16 +pub rsa4096 2018-04-23 [SC]
  17 + 9B06D9B4FA37C4DD52725742747985D7E3CEB635
  18 +uid [ultimate] Su Shuang (CODE SIGNING KEY) <sushuang@apache.org>
  19 +sig 3 747985D7E3CEB635 2018-04-23 Su Shuang (CODE SIGNING KEY) <sushuang@apache.org>
  20 +sub rsa4096 2018-04-23 [E]
  21 +sig 747985D7E3CEB635 2018-04-23 Su Shuang (CODE SIGNING KEY) <sushuang@apache.org>
  22 +
  23 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  24 +
  25 +mQINBFrd5SYBEADoCBw12lsK1sxn3r879jI50GhRAg5vF0aBql0h2BIJ3d+oYYSm
  26 +nIsK/XGpIk3t6ZhJRXK+le89t8a7vBsU+y0+3+OehxOV63du1wscQU9GPu7IfXhw
  27 +V4YcsGK330+V/GiwBs3EX808fdQrdkfCsaGEJhKJbK2fldUcnNp3M1Y2+DVZqGmb
  28 +I7fRJuEj/S9bcVGWnv40jBbMKjx/8LyP2dxZLyy1+whEUimU9em6Tj+SnyISe1I2
  29 +sLa3lwhWer0rkrz0siGFTgDHaDvLlpL9TV34acj/FOon3XKMtx4neNVmkC3QVi0z
  30 +PSlnX6EV8Fas9ylA4x9bdaUo6zUZKO533ASfC6uEibvE2XSRXYJ0xB2bThcQbkdl
  31 +332JqD1TkyF/UQRel3pUm/bCsv2daKD98ZO+eCbvNNonrip2qXDwJJ5HzlXlThyR
  32 +eN1Og90gXvYix4sbsZgNEIyYSaLri7/GjyMD34GCLQiV/kvc/foaC/hkvz6kVOiq
  33 +/tMHY3KsGYAIF4Z9kuTCwJOwFqgfb+Y15bPRDK84uyCiRhtIubNWY7Euy4bBd3ul
  34 +uazQ9LabBhZaa7HCOMssW+TaB+GondZJTiwnI6MCTJKrKtvb8kzcKR4mNf/dvF0O
  35 +x7zwVBeklMKXjkpOtje/+/XOYKuD3g1BZ/+vrfMFPTZ7y7ASC2ylcKI0/QARAQAB
  36 +tDJTdSBTaHVhbmcgKENPREUgU0lHTklORyBLRVkpIDxzdXNodWFuZ0BhcGFjaGUu
  37 +b3JnPokCTgQTAQoAOBYhBJsG2bT6N8TdUnJXQnR5hdfjzrY1BQJa3eUmAhsDBQsJ
  38 +CAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEHR5hdfjzrY13yIP+wS+Mh86IuIK+zG5
  39 +qr/cncV541RxvIGbv5uCQEbFRIwtR8SJEyx2tu4pIgsaTu93hdwxHFCcOZT2IsXP
  40 +meRWPfhaguDFQArdu4VdOfq2AbMqqByFWRsbwvF8CX8fGMPBCsMp0pzqp0px1uUr
  41 +WlK5hBSVwDHWACElyJE7jmk5K+O7RmDUD2E/pgXid+SiU8W+k9vWj49nHAhStYTm
  42 +SwVQA4Gl7jGCJY5jFwZIRD5/b8kVYjbJFl9CBDD2nOIytrGfMVlhp2OcT1f6yZvZ
  43 +oY2nvWLBUF0SmQzlli3EW9zzsNAXDu3f81kqwa+kC2WqQ3s4bKZKQurN5sCWvoyX
  44 +db+AWedArK+m3fH9y3JFIr5Lu1MwfbgfMfm9EZS4A+3DqLFIsLrmnzbGZ9FCkqsj
  45 +TuvKWOP2H365xH44gHImYKZ92PDdLKE7XArVU5b9qtAimgCDsCjEiXTB4S3NVJGX
  46 +R0RZCttKgnrLHwAad3TeLhktWcjH4TdxNCrNZsHLO9mklGyeM1IxKqba4OdHTmYX
  47 +tYYlixSlAu5vSPa+vDkILRfyU87n9YD9RiVGmvy27IP7wdxSClJun6+9fviU2NpG
  48 +FCkLZovYz8/Qht1c8yQZGscw3sa316m1nJz42Lo+p2s6AQZhZupu8bi/W85VHoxa
  49 +roRO16i+mFr4bnbo2/jftB6UVVo7uQINBFrd5SYBEACVsgwBHz5cpBqZQVNS6o0W
  50 +RUnWWNDiBYidNQNTWCF9NDF0HCh6oHecjjXQEPduvMPdzOPpawAkKMRG+7MlHiu/
  51 +ugAq0RluoM3QzDZwvCPw+p/NTESZMqLvbHXEs2u6YCdIsFcTLXr2d+JBWDeGri0S
  52 +YB4gjjQIVvDGqG0tDoW4JmqHHMZiJ6c+h2Rq+saHte0rctHcVAq4p5I8O1iJ1Mkg
  53 +gKJ/TBsjPM5aK6ahPpIPPh48nbhpsLjKHwqB/UWdUcB/HUDa0YfV4JbJilEeeQFZ
  54 +PzlP5SJaGyuEnTnhEwnoXpFetfMYi+Mxnc4VoSrQ3UOsVpD2Ii3haUjdKWTjukyn
  55 +o3sCxvsBTQ8jyBtjjhLw1jfWJdHJ2WCDGVtQVuJ6Gx1GCV0XRbKDTWdIBnCkdKtU
  56 +FY+VMt77oQ/ydeRsZDXhkdgBqqkvdiRHRyEFy72rx61cGTIKuKcWu0rJx8/LnVyi
  57 +nOEk8K8mgNR8omnpFmkkStOtSDLjDb8WeIdigxwJ4wtQnLlLGWiAAVNnDDsqgGIB
  58 +3rrR+/HKUa05CwKI1oIC7i4f7qkgfFUjjr1e496FDSq2tBTLukq/v5FpU6C0JSVq
  59 +MeD5+UuGtSezBxQUdxV7caftIptopwWnx4bBjWSuk2FVCzWcYMnXNIbtfEbqMKuS
  60 +mrpk4mOBNAV6XYzNcOHQqwARAQABiQI2BBgBCgAgFiEEmwbZtPo3xN1ScldCdHmF
  61 +1+POtjUFAlrd5SYCGwwACgkQdHmF1+POtjXK4g//c7vJXmN0FtACspBJVrgsKrYj
  62 +ha4c2PCEynfKSwhVXW3yHnQMwh8/bpQUs5bwCTWx27IEeBrfb03/X9tlx12koGvl
  63 +LujaR7IP6xaqWpbh6rrfttOKGx3xKopJ4nHgNPIYN/ApflAacwyOd+/leWOjHrii
  64 +JXbB60oc7FNvfQRREICLZyeAnzlAcEOVcWvBTngB0EDUZucKwkQtt0x3YvKetgQf
  65 +EMFBAH4RUXG0ms85acX2rpi/kbdarFv6Hc2pzakoWDKNjHMMae1J8wQbPRaXx1NB
  66 ++xF362eLXZaxtvKdzs9Q03R46DY9cyQRofG5WNnZapgemEzPgixur8FYK5EPCQkh
  67 +Y2FA0WUbZFIkO7pE7UNS5ZN5fHkkEhAFo4wV0uqWRVBpFrjKeBxtRkIaw7jLCHr5
  68 +3EpkTusjT/529rEYIq9cGOTwf75AbKR1IZFxffEZYOU76y6SH0bINoYp0VxFJ/IR
  69 +zy5CHqvyUQVUed5O/7UzkYx0IVBGk2wSwOtC7+iRptqj+kI9RCjGizhNe4hG3SUq
  70 +1qkUGkQu6+skyXeFCR1PIAbQgleRNUQotsh/rfsfZpQOomBdvDRPT8ZcN5bjUIJ1
  71 +5c4abryWPkun+BgZk+YFtYLbGZVJAUy2OtXRG5uYzeLc5ID+X5XwwtZOO4gSWMTh
  72 +oQH7TsthVKvdZyjtZQg=
  73 +=Uv8d
  74 +-----END PGP PUBLIC KEY BLOCK-----
  75 +
  76 +pub rsa4096 2019-01-24 [SC]
  77 + 1683FBD23F6DD36C0E52223507D78F777D2C0C27
  78 +uid [ultimate] Ovilia (CODE SIGNING KEY) <oviliazhang@gmail.com>
  79 +sig 3 07D78F777D2C0C27 2019-01-24 Ovilia (CODE SIGNING KEY) <oviliazhang@gmail.com>
  80 +sub rsa4096 2019-01-24 [E]
  81 +sig 07D78F777D2C0C27 2019-01-24 Ovilia (CODE SIGNING KEY) <oviliazhang@gmail.com>
  82 +
  83 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  84 +
  85 +mQINBFxJWEYBEADYzZRcG+WIllHo8PloMv9pX2QZxmZiVJzM7Prgg8KlWfHnO68/
  86 +7Et//hMA2zexJWweZwM0ffmjvcIIEre23De6KaA2htM/54aPoBweDAOBi34RsdR9
  87 +kpN0RvipvJMMZKGB0tDSB3mLhWaiApDGMsysfJAgTaGsIISrC2+xLO/+HxgoEAIX
  88 +a0BTJ+P3cOLPghBBaRtyKNWJjJ2e4XzlVM0T4bM06QmzC0qWTSufKqk1XAZTSOGU
  89 +LXYESonSu/+kL2TCsKi90THNX69a9SBx3DAohbb5WKjXkYistSQi9S33jqZMIc7n
  90 +I1kG1x39YxZiQwwszwbfa3/+qE3X0Qjp2k3fD7wa+qDnSpHTchqy8d71EN0wU6S/
  91 +9vEiJ2e+gxN6WZetK9wl90P70Iu0rvLqSu+5EdkenvIbh6i4CR+Cer1Sky2z7rEY
  92 +vmEjFNjV2ktvbu83RDofxp4ERSbZOwq8VMOWqj6Ft9mIWfw1OAoSkLCRchYFR1ue
  93 +r+e3FuF01KlCXjTV4t24F7l5QO/bwexnmYuVTlSEo4PVZLJAv/UYSP0ngie5DawL
  94 +z2RDCuRrROgtzcf84SaRxwcPNQ0h6EZlKZ4NFL7nl4rwbDsyZRdBqzQ5JPm6dbGe
  95 +CZXCBA84ivcnK845flcsl7ITNjcfsLbeN9s6FMnYZgOHZh/ucmw2dL+5vQARAQAB
  96 +tDFPdmlsaWEgKENPREUgU0lHTklORyBLRVkpIDxvdmlsaWF6aGFuZ0BnbWFpbC5j
  97 +b20+iQJOBBMBCAA4FiEEFoP70j9t02wOUiI1B9ePd30sDCcFAlxJWEYCGwMFCwkI
  98 +BwIGFQoJCAsCBBYCAwECHgECF4AACgkQB9ePd30sDCcgHA//be3mdnRU+jYCP3VU
  99 +l/pcYnbxoIfAhf1Z2orVcN3/E6v2wDYvbvcV7EX/cqwMXBc0/CEVisGQ3zX5CM4/
  100 +C/vwjAsPNPWsX8iyE/Mui/Ktl9tZqQ3/8hTOHe5RQIn0VQ5wIYmyh3Q42BI4vKK3
  101 +BodV9PwONdRhQVJ15x1fp59wiPTqflcXJ0qdGml3JY4ULLFYh63MBV4as6pg/Qtb
  102 +1enZmw8/Bgg6mhY6HiBI+v+8wAwdatwYuG33JdzhoPVbjsnovqAE+kMvOuxmVbK/
  103 +q5dwdwFULbyHzojNAj7zg1zjtksawP8Uspc02JHr16pW3u48E2/uk6XCkTpFDJ09
  104 +xqwtZyEGSobl/9BaDuidXQ9UDsrOIYuvBXO53vlVv1nwzyF7qUhNRNn1HdzIbEiV
  105 +16CaYT5Soy4Xh5sFTFoIg0g/E8JquSgIEJN/NutqbQOHO4ldMxaDEgFp7dRJ/tqo
  106 +CEJgahC/D16efbIUP2gVScYsJK3VYNjuEfnTu2qiR7XDXosG0zGOMGsr4xCuSx8y
  107 +mwtrqRZdl4wfaHi2/QojJGAXwd1Q9WNBxYKuE31amAo7AxGKZ8QLZ9m0RwitG912
  108 +yP7gsw9k/TA195GJiQ5W1qNTHa4gKXhzFtPqg7s9xhJOkb+GOk6tOCWzts1IJSXa
  109 +oyGerp3bGP4Ho49nipEFjeiUKgW5Ag0EXElYRgEQAMbeZQMWRo9h6RgGm7eLCfz2
  110 +K9Ro9yL0U0Jz8SmNz2I7YoYqg4idPV7D0gBym/502QsalQc427vE4QtJGlNPx8yH
  111 +uXIKD0u9sGadO3wkz3WmPqyVMlAgdzjB9ddoWjeQDYTvJLO1eo4LtVUoSydoOs67
  112 +bBNr9Wi2hIso60+cZGxczI+dTkqvgd+nSrhzG1+N1NPjpGqLUSvjWEZiu4NT1oVd
  113 +4f8C6SpQNkgUbliomLE9Zv8Wkcj8RDU5je+dU8r4fKQy1GtDVGW89QXGKALwTg4F
  114 +4/d+/qbF/ZhfZk3e6dxJV4Slmb+IKWUd5dcEYwXIdYXJuQu84CnEtsnQDsIUCc5V
  115 +Qfk1E4SqEmc0gWsmTlsPKF51VdeDpbqQShGgt+xM65wCL7/JASnuEwr1Jt2pPRDq
  116 +VF9s4APQJi/neuJh1A6RlHU6PFcPXmqjsglMdbfKdc0dzoOcc4OcSFPdAlX935L8
  117 +Tlwrp2dy2ARNTSdCvbXx4Lj+Ru7tIUTjDqIFzRLBdppRU/NO6SpNMoIKkOwrjFYd
  118 +H8nV9z6+nYHfJNR/FfT8LLx7ac/trYwDYWMJhk/h9taOszZ5OpQM4LOrWwyg2HA8
  119 +80H95TcQ0c1/dp5OBfPSNfse75yBJrW0PwtQA3++38PHQQZVhO7J3Ha2Y9/MmLqU
  120 +Ip+rhd38hfkHlkrwCr7tABEBAAGJAjYEGAEIACAWIQQWg/vSP23TbA5SIjUH1493
  121 +fSwMJwUCXElYRgIbDAAKCRAH1493fSwMJ4GVD/9AS8YwflROUAodGe7jBHZ41oye
  122 +4I8AX8iTP1qxww8ydeCBVCz3n3lvEHHP8JfVB0aJwiezUtt/1uV0bTFt9ycxyJS1
  123 +5eIefOVN0wFEsj4pgQfBfSWxI0Yd97m+W1xg5h+aAN9W1MNH6rb1ktHCebW709Vf
  124 +Bs+NfktKww98M134cQlmJSo1pBQEBzKaE5KEvLAiafluAPTkvafZfe+35QQdJAXx
  125 +iLE/ZNJQ8L9lBYZaA5mM/NKNzeEqeSTwfvcIonY5sD2EsgBU/ux6QzjRV5EmteJr
  126 +eg+bCWJnbVvZY/2LVru8NKDgfhTSMN0ocDLaWKW6aQO36TequQNdD09wasdSpQmV
  127 +GoCydtdCVoetGdGm8SZvi6EUgAWH4eI3Su/19V8sVo3kHhJ1d575NJCFwTPvKAre
  128 +s8wgU+7CgTojnMxFmb68p+lLe1qQheyXaa44WQ7d7hmXPIoe3EgMYtMc7tLcKccE
  129 +upu7zWG7BNU97kpUw7nmHKalI/1fKEEAYQUmNm9mNVGKjLVNtuG8jw6Zq0vX1tP9
  130 +mh+T3SMBEnsdzoQ+E31lIDNYTZaEHxt0XupNdjt+uEfASdrD3+8+jlWVkpO3FlZ0
  131 +MhfLdHrk689ty11m+5HlrSU7O1I1wZkt/OlYsZmS1yIpD1hEnOuSjAuqm4D3s+YI
  132 +B4WM8AJSCwl8WlZrRA==
  133 +=wft0
  134 +-----END PGP PUBLIC KEY BLOCK-----
  135 +
  136 +pub rsa4096 2020-08-06 [SC]
  137 + 94BD178077672157652826758E44A82497382298
  138 +uid [ 绝对 ] Shen Yi (CODE SIGNING KEY\) <shenyi@apache.org>
  139 +sig 3 8E44A82497382298 2020-08-06 Shen Yi (CODE SIGNING KEY\) <shenyi@apache.org>
  140 +sub rsa4096 2020-08-06 [E]
  141 +sig 8E44A82497382298 2020-08-06 Shen Yi (CODE SIGNING KEY\) <shenyi@apache.org>
  142 +
  143 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  144 +
  145 +mQINBF8sDHUBEADScBNW9N9I7tu/ytMLp0XSQbyDO64iRsaAic/dnM4ffcZOl1AZ
  146 +fbKTF2jI5ABVIl6mWBx5t8RE5XluyESfnB0au3fa0N1cb9bzjAqPiiTU5l9vF4Np
  147 +u0517j8anqPYYk9n0HCVczaBQLavwa7ulUegnMCvO+WkrapkES3PzF/QDmHEh4iC
  148 +FnPsayrhYvirg7Gwy6gkfkSZvp2jQIt2O3PQmffW1OsxwCf0uNIf4UrXxZ9gi6hc
  149 +O/x1jNNpyfOBJY5es8feIsx+zQu/jZRL5AnLeuqYdODD/IdcT/AsSeFnMkIuYdKl
  150 ++S5DL23Rr5W47mCkRglauIOAFXnVd6cc3I0/TB+8+B1XOE7YBcslPytVmnc00Uwf
  151 +f09a1WF7gTufCQAizIRShHLqSXA8Gebs42g5CLEC7k4v1Yojmwun5UFDlbxERQgj
  152 +00hyDsGYv9Mwk5EokcpB/fyInRU0Niny6kk/siui/nvol0vcqBgwTqRJjfFByX8T
  153 +ck11j7f3mUFq4z/PsVU4pQQpGyuiKLDQm7IJPAsJC/+s7aHAuMS/j3lpitM8j26A
  154 +3x091RsxjfBrCusxb301rzw6F2g4bxTRueoPv9Ie8OW27uykqTgdnnCSjT5LQcN7
  155 +H3dRmfk4UMU+QJTDhIdCzHyMnSGBVmlbbHIMIaoxnqzXFpO1+iGRQs8QcwARAQAB
  156 +tC9TaGVuIFlpIChDT0RFIFNJR05JTkcgS0VZXCkgPHNoZW55aUBhcGFjaGUub3Jn
  157 +PokCTgQTAQgAOBYhBJS9F4B3ZyFXZSgmdY5EqCSXOCKYBQJfLAx1AhsDBQsJCAcC
  158 +BhUKCQgLAgQWAgMBAh4BAheAAAoJEI5EqCSXOCKYVkYP/1n0eL9d5EnDunqxo0dt
  159 +HlfxLSx4l+edORXF+q9p0s7x33AktUZxMMNEbeAAgfrtC8sXg8bMa/NWHvmWVND7
  160 +Qj8nJYVZ/jJSVwwXImsK6EdP8401UM1X3+z7uWy4KepJZQIVd6j8dxhW4QE74mlx
  161 +CLBm9dK5rgxTjcNIKApscBJ6pP2eZBprHNdDW3ttaIMGBfz+nA3IpvH7ADgEkffP
  162 +zc9BjiyCuff3q4qW1PnATJFEQCbBAxU13Y8S7pDRhHHDvuo/GNMAoKm8xWb9OzTz
  163 +u8KistljvZWD1ZBjYxAYIKDqVyyUeH/aN134QsQyra++FFHkTiyYjpn/roSQm3Ww
  164 +eQLXtRK0f12EpDb2pchxSrN3L4wRtzGj3I/u/7z6YXa8nuK29t8CDGTss4kBjDmQ
  165 +2uYNAxFq6EylZU6QzaqvQgv/nhSuJFGlSY3v/4Q1MxB5rn68s2jegi/HXUIbFerf
  166 +KgeJCN8nUtBiSIzVwMo0HMrrNyR4ZdCJa4bxzHspu6Fck4572AKxB3TNFkLYC0s+
  167 +zOQ6b6l0bMgzH4HDj6C0k0+KtikK6Q2U1YXWu1T4MBu8Gq4weGEUDOxc0B1XywA2
  168 +BE+cbOpjHi4lK3n1//RjUR+JL90RuD+JGCB8x2d+Ttm/c19S/KjQc8CsJ9JA5x1H
  169 +wlHqg7br0XQQrbUedY65S6skuQINBF8sDHUBEAC99I/csLsLcrpNXB2JYh8XmtBc
  170 +Vb6aSWCc7kowhdwuqjyXvHMkpy9RZz6hxEkk8XiZC+nrCcrr7DNNFNzh5gx30Ihm
  171 +NyZybaawr/vn5O2Oe0BSTwuhIdk1XjpzDtqpcNT2Qui4eRx/OBcyyX9PJvicBfMq
  172 +53ZNom/3NTZbsXp70uCV8eC97a7g7T+GymRS1u2x7I/Kp+/w0plG11bXnWg2A0EZ
  173 +WHCnmQWBUpqSUW3syfuzqlCFDYWoyVkw2eNtIbhGv9knEKPtU9bewAbo1/2Jk1R2
  174 +FVP5B3VvdY2huzQLzbzHB4zhsJCEjYnvzwPZ0WeIYHmTYJEAulTynBdv9GNX9sdM
  175 +GNXS/ESTFUQDMXbgDBdwVxZOq1Gzwh+grN3lwpS/5wcsSuNhfEfvx37DyLKNiXMo
  176 +5HS/g03kAmmIgH7IWUcM27ZyyKlpxj8ztFFUIdnIUX4biiZCBJnfMuWnNzJM7o/b
  177 +T8PVEEM3wuUT5ih7yT4l/j5pV4WmEbgVdWSrbL/H77GuFHwXYiuzDyH1/E23Hedi
  178 +crd8g47bV0jL1v0TwT4oHtEkAXIU5Nj2+z+ZKSl5SJ0I2tAy86hCpIn/rmbMmtws
  179 +Ce/OHHOu2Mm5KBEK9SyLThMzqYrv5Zux9Xqre+P0LPk/tzxwdG87qKhU0xdPvn6y
  180 +rGaC1OFCT3GmidZl2QARAQABiQI2BBgBCAAgFiEElL0XgHdnIVdlKCZ1jkSoJJc4
  181 +IpgFAl8sDHUCGwwACgkQjkSoJJc4IphtBw/8DsvdVbaaVqMOe/S66R3zn5M22YKU
  182 +AkhQvBQId4rTDUgTiSJ6Ll+Ascr1q2gFupb7iAM4BWAFQji4f8iH51sS9a6I6Oy8
  183 +WK4ftFYDyQU0/hgaF2B0+QE0PN3/88ckBlL3KHhzw0ad/Y2Bp6CGGFNwI9xqC7XT
  184 +t8Y+XCpv9buC7ZVpE/N/yF+2HvVhW7PG+5oB+Qc+Q/G0RK2QX7unOSqLc2pS/n4v
  185 +mBqGc1KAe7iyxOo2Q2G+Q0XTK8g/BUMWACVOuYpOrvteyHJXIYv/VDRu+/pd81G0
  186 +i6B063BzuaDRqwNngLOU6lNcDOgom6gWkCfkg1Nbr009rXyADIg/RHPX1TUAaoFn
  187 +QH0YDIxWfyDvTJ7FgmLVCnXXc88T1du/ROAq5Y+opD3vcDX+egzbKR+oSGbaf6HL
  188 +ASj0haconAOZ7V3sLO9WSITUODzHEUwOuOx+XtaW/JYTm47JeH2r83v+OmBNbAJg
  189 +hT5KINI8iBvor3cUYKAor9ib1192ZHgBjPlrFDMntZZCqKyCvRGRktts4VcH09DD
  190 +szVC2TEeuxgIMuUi73HebjX+fRefcSIkW30ehXVzN/7Ah1SK9IJc9hzVa2ZspUho
  191 +Ias/zRyLSbzHrpCs6KVPLwzOQbyPmXNpjoYuGCq6NX54S7bf8Hn3X8SQmezozLhN
  192 +krvOtK7UUytDTcY=
  193 +=+SBy
  194 +-----END PGP PUBLIC KEY BLOCK-----
  195 +pub rsa4096 2022-03-02 [SC]
  196 + 8ACA4FC874B6B0836DFE70BB52514D7E7CFC32B6
  197 +uid [ 绝对 ] Zhang Wenli (CODE SIGNING KEY) <ovilia@apache.org>
  198 +sig 3 52514D7E7CFC32B6 2022-03-02 Zhang Wenli (CODE SIGNING KEY) <ovilia@apache.org>
  199 +sub rsa4096 2022-03-02 [E]
  200 +sig 52514D7E7CFC32B6 2022-03-02 Zhang Wenli (CODE SIGNING KEY) <ovilia@apache.org>
  201 +
  202 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  203 +
  204 +mQINBGIfP7kBEACe5lPqYdMuQsugMCFN8EdGAoFnytQJGHNIY6fBgIQv/CTTM6oM
  205 +JW5pLERfmlvXs3SDIpdZVQp1JmUjs0SpKV4pDBwJq+bMzxiD0QD+7sZb/zadHBOR
  206 +EfKFBij9lrrft/42FbsLrSA19FNalLniXp0NC8QBl+dLafy6ypPX7iSXCWvB/qiu
  207 +XPFY6yJGi4Jt1vVnTeTz9k17y2oJNRl6eh4CLxuTJwLb11Fuhwy8gC0JWMXd52OF
  208 +P6PcWWPWV5qA/UrtbnwQb0Z8+YiK/nDv5p0e2HOEB+Nnl9KdHIpDaP1dSE4hKkFK
  209 +UjWBXzMSBJAwNObMBDGtiWzeU1kIIkHguEUNbJXLHzIWvNrYbuCYOSsdA4o7QNFr
  210 +quy/Vt39+zu5R5znn1AgoUsCvfhMGKME5d2MDgKsyfh8LTHuqDkWZxj8zgMZxDrX
  211 +p/KZBy/bSjii8V1vgoDl0NuJZrXNHrEGQglLiV7RzQBRfkAI4u+3gd+8Emeny0Ku
  212 +GEXrB2dCj7OoDgR0TXmzZf4U8Stnhr4//Fgn76ca+9mOp6NeZpIvVIiJ0hK3QsUe
  213 +gllD0yEJ7fHGQIX//qfymo+rWdvT+WXz6/251eDb+C9TYosj0lpeW0h4URywarvc
  214 +Nqudz8UEVNe4hETtP7VpKjokEiNgj66T+WrbsBWjT1KWlkOhiVFO+FVV0wARAQAB
  215 +tDJaaGFuZyBXZW5saSAoQ09ERSBTSUdOSU5HIEtFWSkgPG92aWxpYUBhcGFjaGUu
  216 +b3JnPokCTgQTAQgAOBYhBIrKT8h0trCDbf5wu1JRTX58/DK2BQJiHz+5AhsDBQsJ
  217 +CAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEFJRTX58/DK2SccP+wZbwZIu4nI1zzlX
  218 +jljH7wLyvDT/hfEm/cBBvF+IgV/EYfMaNaphzsci1V0X8Dv4LmzsV8HS/pIscekM
  219 +mV9Ua8Lyty0QHdFdcMaZPF0irJ59NXfXVu+SDB5NTVaEPhQHclChdyVQEpbv444p
  220 +FwWtNc2JU7C33NtDnsoTECDKy22rP3E/4vti1OEKvaNPqJ7Cmed/fmjShEvoUl1U
  221 +k34fZlTzAZS8FQk3oIvVZq91B9FekywAOLMTo0QFQdgbHpk3Pu2BQ3xaIwEdTu5n
  222 +jypgx7ljK/1Siczo+VzH7uv5pGyVgeufI07OFOqoyC+gfAhXcZp8pBbVuRm5aO0O
  223 +oyzOLm8qQ9TxXt5XtdZzdbgZ8uMr8ualgTj1XOU3Q8AY/BCZ3i7qqZEPY2lO4O/e
  224 +spS2HGx158soggTH0m7EDx5jas5WS49pWxhZOAq4Z3hDSz3LFYTUOUgq1HJJS2b3
  225 +l11rRaDiuxShpIgr5LfxmbCLL+cGmxcPZGEsJBCszEwhPNRqR5AwvRO2OONGsTel
  226 +Y9PqJRT2+3KXgu/rvBnbAuIxaI8vIy1iP82rTxw8z8QK1qce6BIldho18yOVmCrC
  227 +wLMB+snpVnXyaDKvcNJI3KnfiRA9RyKz13XHsykH02nI0c3O0zFW5Ob+HNCnzlgg
  228 +vd1mG4jAwrTN+/fezrInfMu2YsQzuQINBGIfP7kBEADRINphJ2MWt8/FfacMhiVy
  229 +3a9DKkI/w0xt2OFZuTxK7xAuGeNCJGVrRf/qxM82xR7IApDyxLIZn/+DzYMoFzQs
  230 +r2XQR8sAy2/x8r42xUiSZUtfdztVN+QEu+qCgVYAY//qLZsrSfn0ezv51m/Dw2Q0
  231 +k3euzR4/dbulTnt28z4T1BDnDyEWU7vE0m4qyrrQe9DHmC0iIkg3RY7u6/0UK+Ar
  232 +W+IgLQZnZOwTc4GygFCMst8pWsfnLYpPGt3XSI5Om7OQ0Xf1nyLWBtmxJQRsbU5i
  233 +hDLfR0KTARC8cjReFL1eoe9OT6NXJiQltTvDnrpWXN/3tYFakgPf1JrEHkllgHOM
  234 +zM78/H7FgetIueTjem98Qju0/zvBxxd93kLrSkcLRP2QiD7cdIW9tqCrcKY7k06t
  235 +EG+oVdvQA+W7V5wDxQ+8YYp9l+9ftBZNTXa9q/5e7/qzl4cIY4EPpe3eTxj2K9uM
  236 +wsVtPPk48N819fSNDKXOEpqzTs12tniZC5NBsfB8ZduNmjDhcxRMJRA2RhQWRMG0
  237 +knEsVBFkepnhlg6PhWE1fz9Q/YbmVTni4hSN6YFSpw2da6zpHqStXooSzfEw+IvT
  238 +v4WUbHq9TA0zkPEdHn1s75blf8jO6s6XLGEZBKXM/PGO9QtjkYDOaePfpfoLgQEt
  239 +TGHJSTLcEUS/HQLiqVFPpQARAQABiQI2BBgBCAAgFiEEispPyHS2sINt/nC7UlFN
  240 +fnz8MrYFAmIfP7kCGwwACgkQUlFNfnz8MrY18w//QbqFYRLJLKoqfcZV55W2jtxX
  241 +N71+GvY1DWAQByvcV1h9aChpVXyNjKmNiwAdBDam9RYnArmFQauFyEZpHfOdoEc0
  242 +u+Wsllou/tomsqIMx5AuUpGyCrqPKFsKAuqA15/a6tbhEhDd5gIbSYRVlvNinKqm
  243 +JyuPvfbiKQxo28yV7NMIPpSg9gGSkZiEWTGVQR5603EFnkhrS6n8VZFCKQLlSl1X
  244 +VhyN2U/rjwRkDQUh6DSGMb6OHoeFCW00LqqiFoxtdBru9LYO5NYSbnZzicBsBnJ+
  245 +rEqX0yfyDaSzC21wTH3ARf88CruVYerEPMs6lMDLlHlsdZX9VPxofvA7PGcNiiiI
  246 +xkIfPsE1X5cdy7hnhdpPuWEsV4XoYEn1p3TpRdud2N6OZjZe/Jb6KaNmGbRnCl9L
  247 +Hiftq4uZ8hgIdRMa1FdeXug3dwVyPp6HLjqA7q1mi/f69ywNYT8e1g2YrI1MNEL8
  248 +TJqsONJX5Y5LRdUIdGfQ2KZOOlPqTb1ksdm9+xamLccUz3UCCqQS3GuufUjmLmoi
  249 +WQBNQpzlLXaZtFworBRRXTeq7TYK5lqYCU+d46D1pc4TmFoLlCwdr7kY/taa5pip
  250 +XmpgVv8kY1A+ONjCCk5kDNDWUZbYVEyvdihvUz765fpIoCFM2YfbB8J8fgInRfWB
  251 +RWnk0btbWIvaznWpIWo=
  252 +=QBYg
  253 +-----END PGP PUBLIC KEY BLOCK-----
  254 +pub rsa4096 2022-03-28 [SC]
  255 + EFA5629C5F1FF8D33E016202F16C82C561221579
  256 +uid [ultimate] Zhongxiang Wang (CODE SIGNING KEY) <wangzx@apache.org>
  257 +sig 3 F16C82C561221579 2022-03-28 Zhongxiang Wang (CODE SIGNING KEY) <wangzx@apache.org>
  258 +sub rsa4096 2022-03-28 [E]
  259 +sig F16C82C561221579 2022-03-28 Zhongxiang Wang (CODE SIGNING KEY) <wangzx@apache.org>
  260 +
  261 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  262 +
  263 +mQINBGJBdpIBEACtI4twpy36+vUMwpBQCgbpKzY+KtD95bcoMuy8IepzyQSq+Z2b
  264 +mPfjUIA4e9hSvuPCXMkDTZo3Vj2MskzxsFmS+1Or/y0pfsmx0pgzDQ5voD0ayQo3
  265 +EzDT2LbOOkCkPIpBVnQvh3LFk5/VIJCDqjHPyM6r5moWfmq9x7lfDwqhQrJryK9s
  266 +/7EGvgZT2AR7e5TMVgP021t2HH9xfyp/zF+oZVUPSXnmy9j6yiNyu3DjgHwLY+4O
  267 +RGUqhe+I8wq1l2nul0QW2BvLjouEXftf/Rx+X3k/TRVoWtH8RiJzkWZNjd8vyyDd
  268 +cOYo8MxLEJtGDhnrhpsGYM2cYwvGET2mpy1FeX/U/CWfTKUALNxZ4e7GacRi8UeM
  269 +YVp0ov22vskqYKxy0gTVHAoL/mfIcXuCxUw/s0sL01O/rP5lHwy6ghK4KZCTu/4d
  270 +YTfQo8R9NFaBWY9odN3kxJ9ehLPczogtYPU9ThIzbUJ5NudYjh+2NAXEbx9lbfRC
  271 +mR1DyihskYZ4j4FFOWqrke4flDW+lx7VgFb/Um9oQX1Bl7jKRgmlJIN+dNpJpi8w
  272 +9a2DR/gFwxulLvsQPm/Mcki6Xb/Igscq7AZBgUKAtzLMdJuYglp1EUyYhGL6ylIf
  273 +YivzUfNnd6Dvl52H/jLxnZemHy5wO7ZtmehSs3XcPLvM6azb+zCr6xne6QARAQAB
  274 +tDZaaG9uZ3hpYW5nIFdhbmcgKENPREUgU0lHTklORyBLRVkpIDx3YW5nenhAYXBh
  275 +Y2hlLm9yZz6JAk4EEwEIADgWIQTvpWKcXx/40z4BYgLxbILFYSIVeQUCYkF2kgIb
  276 +AwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDxbILFYSIVecLfD/9L/C5XBA5I
  277 +Ub6jS6ozqkupIKdIdLbcXsXNL7cLCrs67zCldHl0t5iaVZF1/rfbwEyjWRD0W6Yx
  278 +k4XPe2iOaOh4R0BBySptBKyK3tyMBOeGZxhtn5w5hZp9ikEbyq/TDK9XK8S+45Zs
  279 +AlfzQ/B0fmihSaMyGNOS2m3kxOMwEOZVegZtiNM+ZSd10/K8Zf5mfdA7EjHLHiow
  280 +WvFMV26gAnd4T7ZRGv7/ZmI0eWAxwdnDdlxE3JgpLfaLjbKWYVOPFxSyF749yFFL
  281 +oRNcTK1Advlwf3jloWhFQU+9i/bsp+VZ7bG3ptfQvq7Nnm+TkVHpHB4FaMnezrJL
  282 +5rKATGZapA9c5MLye0OGGfZAzfvbFsE4J7e1J6mgatjPbMoPjsYBHW5N89ZaBfbQ
  283 +napQuGx2HrBSIzmIaoQqUwdsMaC9cfNx8IdSsbK31maXyY4cooQnGbt4hrALEcti
  284 +DVZCty6NsTLruNk+kCIKLTgMdXYbvJTydNF8bGWppDaEUayRCyCUHf/UBhVhdLU6
  285 +/jyNF141xlNUV5yXDlMGANrZ+26Bu8vufEpkiABihjh/DGQZpdqY9zEDR5sQmae+
  286 +ij0CBG7SLtEFLY5bHsCxm5orSIil0eTAsNFkjn9JYvoil7WJNuV2TdWbSa+Fs+gM
  287 +UmLLR5oUA3EM1T1BV4TICUevcoSZxdKkIrkCDQRiQXaSARAA6Ci/4XEq5CApLoIJ
  288 +MO+HsmP1orppgqGY1hFM1saQ/1JkgOFjfXlGWNLSkymNpqapDIblHdeC8mXdZJSm
  289 +Qeto8i+wEJI+iKl8iYm/KSt/OpfnxfqmMcFhYRczTDFUdp4/cidxCf1TTjyub1PL
  290 +9Pu6TJ4pqJC4TJ1QYOGVZEsMk+Csg6n33sArmpD4YoZfCQy1unvweSr920A4Y5sJ
  291 +jNn6ntGUhguAeHe165yHv2fIWJb/ur+9Kl/SYdD17I+oGW9EZzyNU/lwXs4/siqD
  292 +nmTzdWQ+/NsfFAIJzVsEwp9687opNOXKlSpaLO8ACGx/nOMUnjfmG9tu4h3bkQtN
  293 +SAALDKRn12V3nB7nqbOdSy2QgyFETn5gO64ZuWD/TSk/3P8Bp8AwHdNDKer3GqH7
  294 +omA7VgKxbRhoeJMKWuihBRJ3y01u614QPgmheSzggGg+NVmwWbq5f8+nH20NVNjX
  295 +dTRACCR/0IjRv2ZitNc48X+lNqMMXQdk9K+EpcQhy4fHAnwqc4iij+moKBBp513n
  296 +mv7h+QWLVYjqOuA1yPLAUFxoYLBEQ1DoHTHCbJ3o6gHk8eiPgoIvtJIZNAc150aj
  297 +scwXmk6KxyZwB4cFtFpzRYMfefDRS2O6t9+lkz83dBT9VKWISoRhh3JXaeoIRkk6
  298 +/RvzPYzwGf3R5ouvwfaAXI4YOqEAEQEAAYkCNgQYAQgAIBYhBO+lYpxfH/jTPgFi
  299 +AvFsgsVhIhV5BQJiQXaSAhsMAAoJEPFsgsVhIhV5AUgQAJN537gtlvtWkj6jPFQR
  300 +hNuoCapc7XicBjtqSUlSg/vbWzPeayhSeX288shNJVmJTD5Wq2UfDuki6W6EEdBu
  301 +pZnPX8xqhBjvOCgei3vZZPqEMKqCxAnbV9CVFJzJZh+u5SLnbOlYVuNh6fp1uaSi
  302 +AcRDgyLaUYBYj14ge42aukQuzCWvdnMcn1fZdN84xnm/dXHTxrmphBJlTfVk2U0+
  303 +bvieQNtqp7V7f18peMEoCBTqNjmDxebaTiyqcqAAWXV0bnH9TVIsjCDdT8HfsHAH
  304 +8Pfn/Tw9WqhIRcvWA1Ld1wrMRHv7oOVzMsvvaBsxR4X4yhXBx2Nn2r/g0Rp5K+2R
  305 +o9QLwPCa0P874LVMmdxdoBSC8GMigoj7R1lBIjyaM5v5ylTu8RVmDSul7xIjb6ek
  306 +tWKjZ/ASFSnA+m5VMBF0Z9bA3v31KvsS4ZQtnXEcAIVrNFkBO9JZrwBPat0WVWx7
  307 +/VQeh7PEtvsQhlKRlWY6xVdLq+DD3p/mHqpIH+YWaqhOa6sde8teN8UpSyp6F13a
  308 +SVM1KUz1U6gH3WEu8aqOmJTVrHq5h3kBUrfiLpc3juBCjrAlY2iY3Fzi5VuBzbnT
  309 +oEg8NMD8Wao5YN22JG30anrmYadZaghIwBz6rEuHmbf5MwcKoK349LptfHV4fhuq
  310 +5B5E6LlMNPTCWmPzYtTm5qZK
  311 +=bbcU
  312 +-----END PGP PUBLIC KEY BLOCK-----
  313 +pub ed25519 2022-12-01 [SC] [expires: 2024-11-30]
  314 + 016736F5612A13D1FD04AA45CC593BC1F4F4EB7A
  315 +uid [ultimate] susiwen <susiwen8@gmail.com>
  316 +sig 3 CC593BC1F4F4EB7A 2022-12-01 susiwen <susiwen8@gmail.com>
  317 +sub cv25519 2022-12-01 [E] [expires: 2024-11-30]
  318 +sig CC593BC1F4F4EB7A 2022-12-01 susiwen <susiwen8@gmail.com>
  319 +
  320 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  321 +
  322 +mDMEY4jDBhYJKwYBBAHaRw8BAQdAlpaQNA7ARfkPVj6EoYARkkGPdLgOmulCwScl
  323 +xGk3+8m0HHN1c2l3ZW4gPHN1c2l3ZW44QGdtYWlsLmNvbT6ImQQTFgoAQRYhBAFn
  324 +NvVhKhPR/QSqRcxZO8H09Ot6BQJjiMMGAhsDBQkDwmcABQsJCAcCAiICBhUKCQgL
  325 +AgQWAgMBAh4HAheAAAoJEMxZO8H09Ot6gcoBANBsCrZOwZtWCCQB2A6cy0or7q4c
  326 +GdyMJbP7zT5tdAAuAQDI7dy5/KE5tklZmEHJZevQLWezs6yKi+31QxcNFh6FA7g4
  327 +BGOIwwYSCisGAQQBl1UBBQEBB0A4z0jb/PpPRt/zILSBzl8XidMvvQAksexms4P4
  328 +D74EcQMBCAeIfgQYFgoAJhYhBAFnNvVhKhPR/QSqRcxZO8H09Ot6BQJjiMMGAhsM
  329 +BQkDwmcAAAoJEMxZO8H09Ot6hEABALEBaZSNzmx17PbubyiyvtaEISuzsv23RYwh
  330 +4NRHP4BkAP475WSjwMns2hSairvPXULqAcqQnjytov7CU1hbMLvgDpgzBGOMr5EW
  331 +CSsGAQQB2kcPAQEHQF85ZZTr9NstXxkToCrkVYwNuahidgRyv6S3zo2xTc6ZtC9z
  332 +dXNpd2VuIChDT0RFIFNJR05JTkcgS0VZKSA8c3VzaXdlbjhAZ21haWwuY29tPoiT
  333 +BBMWCgA7FiEEhBIjSy5LUgkGNSGQJZ0/SMJTSzwFAmOMr5ECGwMFCwkIBwICIgIG
  334 +FQoJCAsCBBYCAwECHgcCF4AACgkQJZ0/SMJTSzyNaAD+P35MI4r5nUDDg97QKYNY
  335 +m99MtUxTmcK/KGsrxYEZEDEA/jECGFvy/5WAhIRUTl4ExVsY3eBL/K2DaoTseW4a
  336 +eVEPuDgEY4yvkRIKKwYBBAGXVQEFAQEHQKNPmeMoqbHBVs5xn0c+Tz/bPW0rDDbw
  337 +Gt1pqdBMdmUvAwEIB4h4BBgWCgAgFiEEhBIjSy5LUgkGNSGQJZ0/SMJTSzwFAmOM
  338 +r5ECGwwACgkQJZ0/SMJTSzxTzQD+MTFHjt7z78fdTqbbRA6isxPV84cAFQsX4cRx
  339 +PRobcbkBAIwAkq+ddEycxZTdzaELpE08h/BLcScqbOl/ME1PTZ0H
  340 +=3Tm4
  341 +-----END PGP PUBLIC KEY BLOCK-----
  342 +pub ed25519 2023-03-15 [SC] [有效至:2025-03-14]
  343 + 9C8B166777DB15AD1CC0FFBF715559B9217D4E5A
  344 +uid [ 绝对 ] zakwu <123537200@qq.com>
  345 +sig 3 715559B9217D4E5A 2023-03-15 zakwu <123537200@qq.com>
  346 +sub cv25519 2023-03-15 [E] [有效至:2025-03-14]
  347 +sig 715559B9217D4E5A 2023-03-15 zakwu <123537200@qq.com>
  348 +
  349 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  350 +
  351 +mDMEZBE+JRYJKwYBBAHaRw8BAQdA4US4FlrxvH2Ckj5NzIkeL5nd4NyDBrlpyERo
  352 +KvlXn/C0GHpha3d1IDwxMjM1MzcyMDBAcXEuY29tPoiZBBMWCgBBFiEEnIsWZ3fb
  353 +Fa0cwP+/cVVZuSF9TloFAmQRPiUCGwMFCQPCZwAFCwkIBwICIgIGFQoJCAsCBBYC
  354 +AwECHgcCF4AACgkQcVVZuSF9TloeGAD/RjarHn34jh1NtJGi6Z8wv/XWESxyNH6g
  355 +orBPlQ+yluEBAIinhY8j/XczJQUcj9cqpMB4m8R+/jEadbaBe9pQ3uAHuDgEZBE+
  356 +JRIKKwYBBAGXVQEFAQEHQPa8rnpAhbsWw0VsCbYo1J+VeZXT/piqPpdducN3Wyh2
  357 +AwEIB4h+BBgWCgAmFiEEnIsWZ3fbFa0cwP+/cVVZuSF9TloFAmQRPiUCGwwFCQPC
  358 +ZwAACgkQcVVZuSF9Tlrc4QD/ZDd7OjcT9ShdARjcGoQ0jt6rEqL6n10V6caG+77a
  359 +89wA/R+29UlbOXNAxcQHxph8WXUZhACDhKyNETgRsgHysZQJ
  360 +=/6bg
  361 +-----END PGP PUBLIC KEY BLOCK-----
  362 +pub rsa4096 2024-01-31 [SC]
  363 + 88AF48720040B150083A7D10932517D290673A7B
  364 +uid [ 绝对 ] Zhang Wenli <ovilia@apache.org>
  365 +sig 3 932517D290673A7B 2024-01-31 [自签名]
  366 +sub rsa4096 2024-01-31 [E]
  367 +sig 932517D290673A7B 2024-01-31 [自签名]
  368 +
  369 +-----BEGIN PGP PUBLIC KEY BLOCK-----
  370 +
  371 +mQINBGW5/b0BEADXtrbzMa25cgPBGA0Zta/gdAO2eW8KThwEr9rbxRMZnlh7PUN5
  372 +zxfUn0fbGpQ+GHY5PaMcK350L82Pvz1uTMJDR5frxW/BlTvf83c3YwtjkV+YPk3j
  373 +BN0XTe61EDB3ePc9OpXapoSCncobSeyiKVlpSwM+l9omzAWJZ1cKpGHOaVNLV+0c
  374 +xz3u4cSKG9t/dGFcsExmI9amVYYMv/Hudrj97aAv1lKBWscxo/x9mxNlbGfaIjhR
  375 +3S5BiwKyhSM0CC6pOEGp6HLm3F7dZO/3xF9dCVJEtHtlOchf8umMQMbPH6SSF1lA
  376 +MEDmejlE1MIeL+wVyQ3BbvdANwQ0SYBx1o3e3TUuXOIUz2rZahf4YCNmuB62UHXY
  377 +IbZ83vC3uRpypIzVsGLe4lSHPsG+fGisJHp8JNeDxAnLv8Sdn89XCp7rgX8KLg8K
  378 +Qk4KW0VmwjvxCbQIMssQzP6R5Pq6vOZHCm3Ghsuxx66uSxEG6tBunjjdPMr6oAaa
  379 +DwnJE7BmhC76A0fWQg39Y9nZLm9Zawc7pATz6JM0i5QT/0CLQooqlLAvplNocH4p
  380 +lVFnBugoXh6zXSKhl3MdU5w3EHfOXLNpqbfC9cHoGfJ1miUNkDFJ5ceCgukAlXuV
  381 +5h2pisvOhyK0IkAJJGSuh3Y4z5uFKNlptxz7XTq/VQZV92zAooJX8G1GZwARAQAB
  382 +tB9aaGFuZyBXZW5saSA8b3ZpbGlhQGFwYWNoZS5vcmc+iQJRBBMBCAA7FiEEiK9I
  383 +cgBAsVAIOn0QkyUX0pBnOnsFAmW5/b0CGwMFCwkIBwICIgIGFQoJCAsCBBYCAwEC
  384 +HgcCF4AACgkQkyUX0pBnOnt1ZQ/9HimWDMPJycmOeeiyR3/8rHIJuYz6bmYapyIV
  385 +G7j6gwsliFofaAR2sQ+Kn9by6D2VxMJ892YRvV0HEpvz6zEKOywbVPmWpyHXT8aQ
  386 +rZQvcrL4CcV8lVsFNiQG4kopEIQriq2NmLDvpO+PMnYgrY3tbpEqE3i+A6hbFH7w
  387 +Q3yCpy3MLesDs3pjRJ14EzKm8ecthABcKZxgBHPPjPoxLFtADRNkxX2MgOXygB0R
  388 +5DQKgiUauZv2Le1x+ER8ewspmOoQayIJxjAwDOmttMtFtgk4LO/vNJWyGwdlFmM0
  389 +zfH45Uyw4tj9eau+Noixt6KqHDi9IoiMXRPfBYVaUEfUVTqumOZaNDLd9aLJGZ7p
  390 +/+UjwhAOskN01t5aQrKNNeBCO42PVMjBviwSEwaNP3S05HYeQleu77c4pKA6XzHl
  391 +fRk7WkIWlPIPKhcHKc0EhfivZW6JE3h1pZKiumZjiAAJSOIWcwzWn44EmbbClOAM
  392 +u15CKTvFxzFj7pSwK5jKOX9NcqDc/umfQMCgZnhuUZibCPvvVpBYYcE1cvIYxtMr
  393 +tAKD5d4NMLeB7iT1cmXvCcBj0vyUpYt3B3xzfH0HYL7gZWQA7S2zb9M/lbq9R4MI
  394 +MbTzT7R1rOojY3soz70r0v6+XTExEuV9U6QkO5B43bTkjekIhbVNQS0TvEWfDP5u
  395 +4uUqJuK5Ag0EZbn9vQEQAPglK8p/LjDyi61xxoKniEriqqljQwFk1dHMfJDuIsZw
  396 +T3B21QlY6sfSXk5cKu3sFRb6fSn21isYnSzkJRrhMSVEFoFd8+Fu7ZaLfZDuO6n4
  397 +F6i5Ely0j8G7zkU7+pQPKE9fpdvHvdrJ3SFRqZFALuwgxkMm9JnnvhCAQizKItZ8
  398 +lj6mMJjV/Xe29jBlRXrwY/XTUvJOwrWqicAbeHkY3aDsEGpyB9CKTJWeFRJ9QHVw
  399 +8azhK23lmvoDisiK2fsByp0xqLsolVNV+/k7cgrXZ1Gs1eiBI5bi9ai7tHuaknOb
  400 +BE8EJh9CSBRFnMMhrAb9diaZOQ4ir4kjo0LCs0jOiH6BxlafQpQZW+rDgpYVutaJ
  401 +QOX3daPju3YQIDKTRGHO37ojFPYzxf0i8zkGBAJuRHcaIKynI0KVExwu91JkFRLR
  402 +uhcPIFF8NH8cajaHSxJlQyQPSBGubm7AsKjUUYWXBrH5rtiz7ReYFty+cz3fa8Rm
  403 +aodqqB6ns37rwUD+lZFd3m+Wew9/TDOLP2TFyJctjNIYFGMf9/NYB9+X9fAAZtbl
  404 +QdRiS31V+gyW8LIkS2qypJlyQLNicydvKYl7wnas9lEaHDSQjgdg/+spmRkZuOVg
  405 ++WwiVlEwkCH9SbYi1NXzHzOtAwdrZm2VKx/X+woMRuS1V6DHGTQVi+aScuE+SzF/
  406 +ABEBAAGJAjYEGAEIACAWIQSIr0hyAECxUAg6fRCTJRfSkGc6ewUCZbn9vQIbDAAK
  407 +CRCTJRfSkGc6e8DYEADEy60L3nfr0odeh04Q2Yev2xPV9TxM+7nfx+ECKUQoJSf3
  408 +m5k09AfIT17eHy/+oIFLSp97XIgt1eL9pCAsn2G6XvbAztUzgcQJZRb+fHcqRNZ7
  409 +fiM0puAkYcq/aKMMNwuL7T6AYDak+bsS0vh1/7woZBEpIS1Ulmu5hH/9ypLhRZ/7
  410 +EwOftAqiPz71ahTfUkrL5V4Ddt2nI4/zfFLpnUaiRokljcdLUCqtearvNUdGQbZ9
  411 +J8AHX0FYYhqcHSKnJDqkfOkhrZiTuo3gMP4nx2429ZC9s5igPZ10Aqd1IY3MrmiT
  412 +0Bv4BmbaiYaUss4IU8rNavrj+mueCFg81YaekxgMOsRRVFxCKPKba0lr55iaPygh
  413 +61FtYQxTasEM/4Sm/rF3rmZpktdCv0bRkVOvZ/8+VpHDdhjg6pmzQVNwp9K2xBg0
  414 +TI6kmvnT5NfjOm6xOlg0dYbDr+PiLITlSigZ3BF2qJcmJGpJejuX0PRzWPiAWkoI
  415 +NW6bo6qDdThmCNuS/FUk/1qyXWebuqTVvxbROomoopak37U5IwZZQ6HMtpHZGz+d
  416 +NcCJmTlyNY+xezQj414blwdPgUq4IASLZrCjD9yuO0tUhsNjgHX+R9x7O2Q86ZeN
  417 +WOQhgLPyfZrMnGjpjo/2v62Cp7yFZSNo+xtvErtMeaDL/ufAIFbaVkyxwvkW6g==
  418 +=YTwy
  419 +-----END PGP PUBLIC KEY BLOCK-----
... ...
  1 +
  2 + Apache License
  3 + Version 2.0, January 2004
  4 + http://www.apache.org/licenses/
  5 +
  6 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  7 +
  8 + 1. Definitions.
  9 +
  10 + "License" shall mean the terms and conditions for use, reproduction,
  11 + and distribution as defined by Sections 1 through 9 of this document.
  12 +
  13 + "Licensor" shall mean the copyright owner or entity authorized by
  14 + the copyright owner that is granting the License.
  15 +
  16 + "Legal Entity" shall mean the union of the acting entity and all
  17 + other entities that control, are controlled by, or are under common
  18 + control with that entity. For the purposes of this definition,
  19 + "control" means (i) the power, direct or indirect, to cause the
  20 + direction or management of such entity, whether by contract or
  21 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
  22 + outstanding shares, or (iii) beneficial ownership of such entity.
  23 +
  24 + "You" (or "Your") shall mean an individual or Legal Entity
  25 + exercising permissions granted by this License.
  26 +
  27 + "Source" form shall mean the preferred form for making modifications,
  28 + including but not limited to software source code, documentation
  29 + source, and configuration files.
  30 +
  31 + "Object" form shall mean any form resulting from mechanical
  32 + transformation or translation of a Source form, including but
  33 + not limited to compiled object code, generated documentation,
  34 + and conversions to other media types.
  35 +
  36 + "Work" shall mean the work of authorship, whether in Source or
  37 + Object form, made available under the License, as indicated by a
  38 + copyright notice that is included in or attached to the work
  39 + (an example is provided in the Appendix below).
  40 +
  41 + "Derivative Works" shall mean any work, whether in Source or Object
  42 + form, that is based on (or derived from) the Work and for which the
  43 + editorial revisions, annotations, elaborations, or other modifications
  44 + represent, as a whole, an original work of authorship. For the purposes
  45 + of this License, Derivative Works shall not include works that remain
  46 + separable from, or merely link (or bind by name) to the interfaces of,
  47 + the Work and Derivative Works thereof.
  48 +
  49 + "Contribution" shall mean any work of authorship, including
  50 + the original version of the Work and any modifications or additions
  51 + to that Work or Derivative Works thereof, that is intentionally
  52 + submitted to Licensor for inclusion in the Work by the copyright owner
  53 + or by an individual or Legal Entity authorized to submit on behalf of
  54 + the copyright owner. For the purposes of this definition, "submitted"
  55 + means any form of electronic, verbal, or written communication sent
  56 + to the Licensor or its representatives, including but not limited to
  57 + communication on electronic mailing lists, source code control systems,
  58 + and issue tracking systems that are managed by, or on behalf of, the
  59 + Licensor for the purpose of discussing and improving the Work, but
  60 + excluding communication that is conspicuously marked or otherwise
  61 + designated in writing by the copyright owner as "Not a Contribution."
  62 +
  63 + "Contributor" shall mean Licensor and any individual or Legal Entity
  64 + on behalf of whom a Contribution has been received by Licensor and
  65 + subsequently incorporated within the Work.
  66 +
  67 + 2. Grant of Copyright License. Subject to the terms and conditions of
  68 + this License, each Contributor hereby grants to You a perpetual,
  69 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  70 + copyright license to reproduce, prepare Derivative Works of,
  71 + publicly display, publicly perform, sublicense, and distribute the
  72 + Work and such Derivative Works in Source or Object form.
  73 +
  74 + 3. Grant of Patent License. Subject to the terms and conditions of
  75 + this License, each Contributor hereby grants to You a perpetual,
  76 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  77 + (except as stated in this section) patent license to make, have made,
  78 + use, offer to sell, sell, import, and otherwise transfer the Work,
  79 + where such license applies only to those patent claims licensable
  80 + by such Contributor that are necessarily infringed by their
  81 + Contribution(s) alone or by combination of their Contribution(s)
  82 + with the Work to which such Contribution(s) was submitted. If You
  83 + institute patent litigation against any entity (including a
  84 + cross-claim or counterclaim in a lawsuit) alleging that the Work
  85 + or a Contribution incorporated within the Work constitutes direct
  86 + or contributory patent infringement, then any patent licenses
  87 + granted to You under this License for that Work shall terminate
  88 + as of the date such litigation is filed.
  89 +
  90 + 4. Redistribution. You may reproduce and distribute copies of the
  91 + Work or Derivative Works thereof in any medium, with or without
  92 + modifications, and in Source or Object form, provided that You
  93 + meet the following conditions:
  94 +
  95 + (a) You must give any other recipients of the Work or
  96 + Derivative Works a copy of this License; and
  97 +
  98 + (b) You must cause any modified files to carry prominent notices
  99 + stating that You changed the files; and
  100 +
  101 + (c) You must retain, in the Source form of any Derivative Works
  102 + that You distribute, all copyright, patent, trademark, and
  103 + attribution notices from the Source form of the Work,
  104 + excluding those notices that do not pertain to any part of
  105 + the Derivative Works; and
  106 +
  107 + (d) If the Work includes a "NOTICE" text file as part of its
  108 + distribution, then any Derivative Works that You distribute must
  109 + include a readable copy of the attribution notices contained
  110 + within such NOTICE file, excluding those notices that do not
  111 + pertain to any part of the Derivative Works, in at least one
  112 + of the following places: within a NOTICE text file distributed
  113 + as part of the Derivative Works; within the Source form or
  114 + documentation, if provided along with the Derivative Works; or,
  115 + within a display generated by the Derivative Works, if and
  116 + wherever such third-party notices normally appear. The contents
  117 + of the NOTICE file are for informational purposes only and
  118 + do not modify the License. You may add Your own attribution
  119 + notices within Derivative Works that You distribute, alongside
  120 + or as an addendum to the NOTICE text from the Work, provided
  121 + that such additional attribution notices cannot be construed
  122 + as modifying the License.
  123 +
  124 + You may add Your own copyright statement to Your modifications and
  125 + may provide additional or different license terms and conditions
  126 + for use, reproduction, or distribution of Your modifications, or
  127 + for any such Derivative Works as a whole, provided Your use,
  128 + reproduction, and distribution of the Work otherwise complies with
  129 + the conditions stated in this License.
  130 +
  131 + 5. Submission of Contributions. Unless You explicitly state otherwise,
  132 + any Contribution intentionally submitted for inclusion in the Work
  133 + by You to the Licensor shall be under the terms and conditions of
  134 + this License, without any additional terms or conditions.
  135 + Notwithstanding the above, nothing herein shall supersede or modify
  136 + the terms of any separate license agreement you may have executed
  137 + with Licensor regarding such Contributions.
  138 +
  139 + 6. Trademarks. This License does not grant permission to use the trade
  140 + names, trademarks, service marks, or product names of the Licensor,
  141 + except as required for reasonable and customary use in describing the
  142 + origin of the Work and reproducing the content of the NOTICE file.
  143 +
  144 + 7. Disclaimer of Warranty. Unless required by applicable law or
  145 + agreed to in writing, Licensor provides the Work (and each
  146 + Contributor provides its Contributions) on an "AS IS" BASIS,
  147 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  148 + implied, including, without limitation, any warranties or conditions
  149 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  150 + PARTICULAR PURPOSE. You are solely responsible for determining the
  151 + appropriateness of using or redistributing the Work and assume any
  152 + risks associated with Your exercise of permissions under this License.
  153 +
  154 + 8. Limitation of Liability. In no event and under no legal theory,
  155 + whether in tort (including negligence), contract, or otherwise,
  156 + unless required by applicable law (such as deliberate and grossly
  157 + negligent acts) or agreed to in writing, shall any Contributor be
  158 + liable to You for damages, including any direct, indirect, special,
  159 + incidental, or consequential damages of any character arising as a
  160 + result of this License or out of the use or inability to use the
  161 + Work (including but not limited to damages for loss of goodwill,
  162 + work stoppage, computer failure or malfunction, or any and all
  163 + other commercial damages or losses), even if such Contributor
  164 + has been advised of the possibility of such damages.
  165 +
  166 + 9. Accepting Warranty or Additional Liability. While redistributing
  167 + the Work or Derivative Works thereof, You may choose to offer,
  168 + and charge a fee for, acceptance of support, warranty, indemnity,
  169 + or other liability obligations and/or rights consistent with this
  170 + License. However, in accepting such obligations, You may act only
  171 + on Your own behalf and on Your sole responsibility, not on behalf
  172 + of any other Contributor, and only if You agree to indemnify,
  173 + defend, and hold each Contributor harmless for any liability
  174 + incurred by, or claims asserted against, such Contributor by reason
  175 + of your accepting any such warranty or additional liability.
  176 +
  177 + END OF TERMS AND CONDITIONS
  178 +
  179 + APPENDIX: How to apply the Apache License to your work.
  180 +
  181 + To apply the Apache License to your work, attach the following
  182 + boilerplate notice, with the fields enclosed by brackets "[]"
  183 + replaced with your own identifying information. (Don't include
  184 + the brackets!) The text should be enclosed in the appropriate
  185 + comment syntax for the file format. We also recommend that a
  186 + file or class name and description of purpose be included on the
  187 + same "printed page" as the copyright notice for easier
  188 + identification within third-party archives.
  189 +
  190 + Copyright [yyyy] [name of copyright owner]
  191 +
  192 + Licensed under the Apache License, Version 2.0 (the "License");
  193 + you may not use this file except in compliance with the License.
  194 + You may obtain a copy of the License at
  195 +
  196 + http://www.apache.org/licenses/LICENSE-2.0
  197 +
  198 + Unless required by applicable law or agreed to in writing, software
  199 + distributed under the License is distributed on an "AS IS" BASIS,
  200 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  201 + See the License for the specific language governing permissions and
  202 + limitations under the License.
  203 +
  204 +
  205 +
  206 +
  207 +
  208 +========================================================================
  209 +Apache ECharts Subcomponents:
  210 +
  211 +The Apache ECharts project contains subcomponents with separate copyright
  212 +notices and license terms. Your use of the source code for these
  213 +subcomponents is also subject to the terms and conditions of the following
  214 +licenses.
  215 +
  216 +BSD 3-Clause (d3.js):
  217 +The following files embed [d3.js](https://github.com/d3/d3) BSD 3-Clause:
  218 + `/src/chart/treemap/treemapLayout.ts`,
  219 + `/src/chart/tree/layoutHelper.ts`,
  220 + `/src/chart/graph/forceHelper.ts`,
  221 + `/src/util/number.ts`
  222 +See `/licenses/LICENSE-d3` for details of the license.
... ...
  1 +Apache ECharts
  2 +Copyright 2017-2024 The Apache Software Foundation
  3 +
  4 +This product includes software developed at
  5 +The Apache Software Foundation (https://www.apache.org/).
\ No newline at end of file
... ...
  1 +# Apache ECharts
  2 +
  3 +<a href="https://echarts.apache.org/">
  4 + <img style="vertical-align: top;" src="./asset/logo.png?raw=true" alt="logo" height="50px">
  5 +</a>
  6 +
  7 +Apache ECharts is a free, powerful charting and visualization library offering easy ways to add intuitive, interactive, and highly customizable charts to your commercial products. It is written in pure JavaScript and based on <a href="https://github.com/ecomfe/zrender">zrender</a>, which is a whole new lightweight canvas library.
  8 +
  9 +**[中文官网](https://echarts.apache.org/zh/index.html)** | **[ENGLISH HOMEPAGE](https://echarts.apache.org/en/index.html)**
  10 +
  11 +[![License](https://img.shields.io/npm/l/echarts?color=5470c6)](https://github.com/apache/echarts/blob/master/LICENSE) [![Latest npm release](https://img.shields.io/npm/v/echarts?color=91cc75)](https://www.npmjs.com/package/echarts) [![NPM downloads](https://img.shields.io/npm/dm/echarts.svg?label=npm%20downloads&style=flat&color=fac858)](https://www.npmjs.com/package/echarts) [![Contributors](https://img.shields.io/github/contributors/apache/echarts?color=3ba272)](https://github.com/apache/echarts/graphs/contributors)
  12 +
  13 +[![Build Status](https://github.com/apache/echarts/actions/workflows/ci.yml/badge.svg)](https://github.com/apache/echarts/actions/workflows/ci.yml)
  14 +
  15 +## Get Apache ECharts
  16 +
  17 +You may choose one of the following methods:
  18 +
  19 ++ Download from the [official website](https://echarts.apache.org/download.html)
  20 ++ `npm install echarts --save`
  21 ++ CDN: [jsDelivr CDN](https://www.jsdelivr.com/package/npm/echarts?path=dist)
  22 +
  23 +## Docs
  24 +
  25 ++ [Get Started](https://echarts.apache.org/handbook)
  26 ++ [API](https://echarts.apache.org/api.html)
  27 ++ [Option Manual](https://echarts.apache.org/option.html)
  28 ++ [Examples](https://echarts.apache.org/examples)
  29 +
  30 +## Get Help
  31 +
  32 ++ [GitHub Issues](https://github.com/apache/echarts/issues) for bug report and feature requests
  33 ++ Email [dev@echarts.apache.org](mailto:dev@echarts.apache.org) for general questions
  34 ++ Subscribe to the [mailing list](https://echarts.apache.org/maillist.html) to get updated with the project
  35 +
  36 +## Build
  37 +
  38 +Build echarts source code:
  39 +
  40 +Execute the instructions in the root directory of the echarts:
  41 +([Node.js](https://nodejs.org) is required)
  42 +
  43 +```shell
  44 +# Install the dependencies from NPM:
  45 +npm install
  46 +
  47 +# Rebuild source code immediately in watch mode when changing the source code.
  48 +# It opens the `./test` directory, and you may open `-cases.html` to get the list
  49 +# of all test cases.
  50 +# If you wish to create a test case, run `npm run mktest:help` to learn more.
  51 +npm run dev
  52 +
  53 +# Check the correctness of TypeScript code.
  54 +npm run checktype
  55 +
  56 +# If intending to build and get all types of the "production" files:
  57 +npm run release
  58 +```
  59 +
  60 +Then the "production" files are generated in the `dist` directory.
  61 +
  62 +## Contribution
  63 +
  64 +Please refer to the [contributing](https://github.com/apache/echarts/blob/master/CONTRIBUTING.md) document if you wish to debug locally or make pull requests.
  65 +
  66 +## Resources
  67 +
  68 +### Awesome ECharts
  69 +
  70 +[https://github.com/ecomfe/awesome-echarts](https://github.com/ecomfe/awesome-echarts)
  71 +
  72 +### Extensions
  73 +
  74 ++ [ECharts GL](https://github.com/ecomfe/echarts-gl) An extension pack of ECharts, which provides 3D plots, globe visualization, and WebGL acceleration.
  75 +
  76 ++ [Liquidfill 水球图](https://github.com/ecomfe/echarts-liquidfill)
  77 +
  78 ++ [Wordcloud 字符云](https://github.com/ecomfe/echarts-wordcloud)
  79 +
  80 ++ [Extension for Baidu Map 百度地图扩展](https://github.com/apache/echarts/tree/master/extension-src/bmap) An extension provides a wrapper of Baidu Map Service SDK.
  81 +
  82 ++ [vue-echarts](https://github.com/ecomfe/vue-echarts) ECharts component for Vue.js
  83 +
  84 ++ [echarts-stat](https://github.com/ecomfe/echarts-stat) Statistics tool for ECharts
  85 +
  86 +## License
  87 +
  88 +ECharts is available under the Apache License V2.
  89 +
  90 +## Code of Conduct
  91 +
  92 +Please refer to [Apache Code of Conduct](https://www.apache.org/foundation/policies/conduct.html).
  93 +
  94 +## Paper
  95 +
  96 +Deqing Li, Honghui Mei, Yi Shen, Shuang Su, Wenli Zhang, Junting Wang, Ming Zu, Wei Chen.
  97 +[ECharts: A Declarative Framework for Rapid Construction of Web-based Visualization](https://www.sciencedirect.com/science/article/pii/S2468502X18300068).
  98 +Visual Informatics, 2018.
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +export * from './types/dist/charts';
\ No newline at end of file
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +
  21 +// In somehow. If we export like
  22 +// export * as LineChart './chart/line/install'
  23 +// The exported code will be transformed to
  24 +// import * as LineChart_1 './chart/line/install'; export {LineChart_1 as LineChart};
  25 +// Treeshaking in webpack will not work even if we configured sideEffects to false in package.json
  26 +
  27 +export * from './lib/export/charts.js';
\ No newline at end of file
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +export * from './types/dist/components';
\ No newline at end of file
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +export * from './lib/export/components.js';
\ No newline at end of file
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +export * from './types/dist/core';
\ No newline at end of file
... ...
  1 +/*
  2 +* Licensed to the Apache Software Foundation (ASF) under one
  3 +* or more contributor license agreements. See the NOTICE file
  4 +* distributed with this work for additional information
  5 +* regarding copyright ownership. The ASF licenses this file
  6 +* to you under the Apache License, Version 2.0 (the
  7 +* "License"); you may not use this file except in compliance
  8 +* with the License. You may obtain a copy of the License at
  9 +*
  10 +* http://www.apache.org/licenses/LICENSE-2.0
  11 +*
  12 +* Unless required by applicable law or agreed to in writing,
  13 +* software distributed under the License is distributed on an
  14 +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15 +* KIND, either express or implied. See the License for the
  16 +* specific language governing permissions and limitations
  17 +* under the License.
  18 +*/
  19 +
  20 +export * from './lib/export/core.js';
\ No newline at end of file
... ...